Download index.html from getreadystack/crypto-export-notice-lint: direct link, hf CLI and curl.
- Browser
- Download file 41.3 kB
-
https://huggingface.co/spaces/getreadystack/crypto-export-notice-lint/resolve/main/index.html
- Command line
-
hf download hf://spaces/getreadystack/crypto-export-notice-lint/index.html
-
curl -L -o index.html https://huggingface.co/spaces/getreadystack/crypto-export-notice-lint/resolve/main/index.html
41.3 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width,initial-scale=1"> | |
| <title>EAR 742.15 checklist — check your notice in browser</title> | |
| <meta name="description" content="This free tool checks a README or export notice against the listed US EAR 742.15(b) publication items."> | |
| <style> | |
| :root{color-scheme:light}body{margin:0;font:15px/1.55 system-ui,-apple-system,"Segoe UI",sans-serif;background:#faf9f5;color:#1a1512} | |
| .wrap{max-width:960px;margin:0 auto;padding:28px 18px 60px}h1{font-size:26px;margin:0 0 6px}.lede{color:#4a403a;margin:0 0 16px} | |
| textarea{width:100%;min-height:260px;font:13px/1.45 ui-monospace,Menlo,Consolas,monospace;padding:12px;border:1px solid #d9d0c4;border-radius:8px;box-sizing:border-box} | |
| .bar{display:flex;gap:10px;align-items:center;margin:12px 0}button{font:600 15px system-ui;padding:10px 18px;border:0;border-radius:8px;background:#1a1512;color:#fff;cursor:pointer} | |
| input[type=date]{font:14px system-ui;padding:8px;border:1px solid #d9d0c4;border-radius:6px} | |
| table{border-collapse:collapse;width:100%;font-size:14px;margin-top:10px}th,td{text-align:left;padding:8px 10px;border-bottom:1px solid #eee;vertical-align:top}th{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:#7a6e65} | |
| .sev.error{color:#a8551f;font-weight:700}.sev.warn,.sev.warning{color:#96691f}.ok{color:#2a6446;font-weight:600}.sum{font-weight:600} | |
| .note{font-size:13px;color:#7a6e65;margin-top:18px}#paid{margin-top:22px;padding:14px 16px;border:1px solid #e2d8cb;border-radius:10px;background:#fffdfa} | |
| </style> | |
| <script data-grow-initializer="">!(function(){window.growMe||((window.growMe=function(e){window.growMe._.push(e);}),(window.growMe._=[]));var e=document.createElement("script");(e.type="text/javascript"),(e.src="https://faves.grow.me/main.js"),(e.defer=!0),e.setAttribute("data-grow-faves-site-id","U2l0ZTphZjljMzgyMC0yMmU5LTRhYjgtYTIxNS03OTRhMGY1N2ExYzM=");var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t);})();</script> | |
| <!--yj-canon-s101--><link rel="canonical" href="https://getreadystack.com/tools/crypto-export-notice-lint"></head> | |
| <body> | |
| <div class="wrap"> | |
| <h1>EAR 742.15 checklist — check your notice in browser</h1> | |
| <p class="lede">Checks a README or EXPORT notice against the US EAR 742.15(b) publication items: BIS and NSA emails, published source URL, ECCN line, notification date, and the removed 740.13(e) citation. Runs entirely in your browser — nothing is uploaded.</p> | |
| <textarea id="src" spellcheck="false"># VaultBox | |
| VaultBox encrypts a team's secrets at rest with AES-256 and ships a TLS 1.3 sync client. Install it with npm and point it at your own storage bucket. | |
| ## Export notice | |
| This project is publicly available open source, so it is not subject to the EAR and no export licence is required to download it. We publish the source under License Exception TSU (EAR 740.13(e)) and treat the package as EAR99 for customs paperwork. | |
| The notification email was sent to crypt@bis.doc.gov on 2019-03-04 when the first release went out. Source: https://github.com/example/vaultbox | |
| ## Licence | |
| MIT.</textarea> | |
| <div class="bar"><button id="go">Check</button><label>as of <input type="date" id="today"></label></div> | |
| <div id="out" aria-live="polite"></div> | |
| <div id="paid"><strong>Free here:</strong> Check the README or EXPORT notice open in the editor against all 10 checks. <strong>In the editor:</strong> Sweep every Markdown file in the repository and write a dated export-notice report you keep — that part asks for a licence key.</div> | |
| <p class="note">Same engine as the VS Code extension, byte for byte.</p> | |
| </div> | |
| <script>var XEXPORT_RULES = [ | |
| {"check": "no_export_notice", "sev": "error", "msg": "This file describes encryption but carries no export-control notice. EAR 742.15(b) attaches to the act of publishing the source, not to the release notes."}, | |
| {"check": "missing_bis_email", "sev": "error", "msg": "No crypt@bis.doc.gov in the notice. EAR 742.15(b)(1) asks for an email to BIS with the internet location of the published source code."}, | |
| {"check": "missing_nsa_email", "sev": "error", "msg": "No enc@nsa.gov in the notice. The same 742.15(b)(1) notification goes to the ENC Encryption Request Coordinator as well as to BIS."}, | |
| {"check": "missing_source_url", "sev": "error", "msg": "The notice names no internet location. The URL you emailed is the notification; a notice without it cannot be checked against what BIS received."}, | |
| {"check": "missing_eccn", "sev": "error", "msg": "No ECCN in the notice (5D002, 5E002, 5A002 or 5D992). Publicly available encryption source code is classified before it is published, not after."}, | |
| {"check": "removed_tsu_citation", "sev": "error", "msg": "This notice cites License Exception TSU / EAR 740.13(e) for encryption source code. BIS removed that paragraph in the 20 September 2016 encryption rule and moved the notification to 742.15(b)."}, | |
| {"check": "false_exemption_claim", "sev": "error", "msg": "The notice claims the code is outside export control (or EAR99) because it is open source. Public availability under 742.15(b) is conditioned on the notification; it is not automatic and EAR99 is not a classification for 5D002 encryption source."}, | |
| {"check": "missing_notification_date", "sev": "warn", "msg": "The notice records no date for the notification. Without a date nobody can tell which release the email covered."}, | |
| {"check": "stale_notification", "sev": "warn", "msg": "The recorded notification is from an earlier calendar year. Re-notify on a new internet location, and check the annual self-classification report due 1 February."}, | |
| {"check": "missing_renotify_clause", "sev": "warn", "msg": "The notice does not say what happens when the source moves. EAR 742.15(b)(1) wants a fresh email whenever the internet location changes."} | |
| ] | |
| ;</script> | |
| <script>// Crypto Export Notice Lint — the brain. Same file runs in Node (extension) and in the browser (free web page). | |
| ; | |
| var RULES = (typeof module !== 'undefined') ? require('./rules.json') : window.XEXPORT_RULES; | |
| var CRYPTO = /\b(aes|rsa|tls|ssl|libsodium|openssl|bouncycastle|chacha20|x25519|ed25519|encrypt(?:s|ed|ion)?|cryptograph\w+|cipher|keystore)\b/i; | |
| var HEADING = /^(#{1,6})\s+(.*)$/; | |
| var EXPORT_HEAD = /(export|encryption|cryptograph)/i; | |
| function flat(s) { return String(s || '').replace(/\r/g, ' ').replace(/\s+/g, ' ').trim(); } | |
| function section(lines) { | |
| var start = -1, level = 0; | |
| for (var i = 0; i < lines.length; i++) { | |
| var m = HEADING.exec(lines[i]); | |
| if (m && EXPORT_HEAD.test(m[2])) { start = i; level = m[1].length; break; } | |
| } | |
| if (start < 0) return { found: false, from: 0, to: lines.length, line: 1 }; | |
| var end = lines.length; | |
| for (var j = start + 1; j < lines.length; j++) { | |
| var h = HEADING.exec(lines[j]); | |
| if (h && h[1].length <= level) { end = j; break; } | |
| } | |
| return { found: true, from: start, to: end, line: start + 1 }; | |
| } | |
| function lineOf(lines, from, to, re, fallback) { | |
| for (var i = from; i < to; i++) { if (re.test(lines[i])) return i + 1; } | |
| return fallback; | |
| } | |
| function days(fromISO, todayISO) { | |
| var a = Date.parse(fromISO + 'T00:00:00Z'), b = Date.parse(todayISO + 'T00:00:00Z'); | |
| if (isNaN(a) || isNaN(b)) return null; | |
| return Math.round((b - a) / 86400000); | |
| } | |
| function check(text, opts) { | |
| opts = opts || {}; | |
| var todayISO = /^\d{4}-\d{2}-\d{2}$/.test(String(opts.today || '')) ? String(opts.today) : new Date().toISOString().slice(0, 10); | |
| var lines = String(text || '').replace(/\r/g, '').split('\n'); | |
| var sec = section(lines); | |
| var body = flat(lines.slice(sec.from, sec.to).join(' ')); | |
| var whole = flat(lines.join(' ')); | |
| var findings = []; | |
| var R = {}; | |
| for (var i = 0; i < RULES.length; i++) R[RULES[i].check] = RULES[i]; | |
| function add(id, line, extra) { | |
| var r = R[id]; | |
| if (!r) return; | |
| findings.push({ check: id, sev: r.sev, msg: extra ? r.msg + ' ' + extra : r.msg, line: line || 1 }); | |
| } | |
| var cryptoHere = CRYPTO.test(whole); | |
| if (!cryptoHere) return { findings: findings, rules: RULES.length, today: todayISO }; | |
| if (!sec.found) add('no_export_notice', lineOf(lines, 0, lines.length, CRYPTO, 1)); | |
| if (!/crypt@bis\.doc\.gov/i.test(body)) add('missing_bis_email', sec.line); | |
| if (!/enc@nsa\.gov/i.test(body)) add('missing_nsa_email', sec.line); | |
| if (!/https?:\/\/[^\s)>\]]+/i.test(body)) add('missing_source_url', sec.line); | |
| if (!/\b5[ADE](?:002|992)\b/i.test(body)) add('missing_eccn', sec.line); | |
| var tsu = /740\s*\.\s*13\s*\(?\s*e\s*\)?|license exception tsu/i; | |
| if (tsu.test(body)) add('removed_tsu_citation', lineOf(lines, sec.from, sec.to, tsu, sec.line)); | |
| var bogus = /not subject to (?:the )?(?:ear|export)|no export (?:licen[cs]e|restriction|control)|exempt from (?:the )?(?:ear|export)|\bEAR\s?99\b/i; | |
| if (bogus.test(body)) add('false_exemption_claim', lineOf(lines, sec.from, sec.to, bogus, sec.line)); | |
| var dateRe = /\b(20\d{2})-(\d{2})-(\d{2})\b/; | |
| var dm = dateRe.exec(body); | |
| if (!dm) { | |
| add('missing_notification_date', sec.line); | |
| } else if (Number(dm[1]) < Number(todayISO.slice(0, 4))) { | |
| var n = days(dm[0], todayISO); | |
| add('stale_notification', lineOf(lines, sec.from, sec.to, dateRe, sec.line), | |
| 'Last notification ' + dm[0] + ' — ' + (n === null ? 'unknown' : n) + ' days ago as of ' + todayISO + '.'); | |
| } | |
| if (!/(url|internet location|location|mirror|host|repositor\w+)[^.]{0,140}chang/i.test(body)) add('missing_renotify_clause', sec.line); | |
| return { findings: findings, rules: RULES.length, today: todayISO }; | |
| } | |
| var API = { engine: { check: check }, RULES: RULES, RULE_COUNT: RULES.length }; | |
| if (typeof window !== 'undefined') window.XEXPORTENGINE = API; | |
| if (typeof module !== 'undefined') module.exports = API; | |
| </script> | |
| <script>// ⛔뼈대 — kit/scaffold.py 가 찍는다 (s143). findings [{check,sev,msg,line?}] → 글/HTML. 같은 파일이 Node 와 브라우저에서 산다. | |
| ; | |
| function escapeHtml(s) { return String(s == null ? '' : s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); } | |
| function summaryLine(res) { | |
| const f = (res && res.findings) || []; const e = f.filter(function (x) { return String(x.sev || 'error').toLowerCase().startsWith('err'); }).length; | |
| return f.length ? (f.length + ' finding' + (f.length === 1 ? '' : 's') + ' (' + e + ' error' + (e === 1 ? '' : 's') + ')') : 'Clean — no findings.'; | |
| } | |
| function toText(res, label) { | |
| const f = (res && res.findings) || []; | |
| const lines = ['== ' + (label || '') + ' — ' + summaryLine(res)]; | |
| f.forEach(function (x) { lines.push(' ' + String(x.sev || 'error').toUpperCase().slice(0, 4) + ' ' + (x.line ? 'L' + x.line + ' ' : '') + (x.check || x.id || '') + ' ' + (x.msg || x.message || '')); }); | |
| return lines.join('\n'); | |
| } | |
| function toHtml(res) { | |
| const f = (res && res.findings) || []; | |
| if (!f.length) return '<p class="ok">' + escapeHtml(summaryLine(res)) + '</p>'; | |
| const rows = f.map(function (x) { return '<tr><td class="sev ' + escapeHtml(String(x.sev || 'error')) + '">' + escapeHtml(String(x.sev || 'error')) + '</td><td>' + (x.line ? 'L' + escapeHtml(x.line) : '') + '</td><td><code>' + escapeHtml(x.check || x.id || '') + '</code></td><td>' + escapeHtml(x.msg || x.message || '') + '</td></tr>'; }).join(''); | |
| return '<p class="sum">' + escapeHtml(summaryLine(res)) + '</p><table><thead><tr><th>Level</th><th>Line</th><th>Check</th><th>What</th></tr></thead><tbody>' + rows + '</tbody></table>'; | |
| } | |
| var XEXPORTREPORT = { escapeHtml: escapeHtml, summaryLine: summaryLine, toText: toText, toHtml: toHtml }; | |
| if (typeof module !== 'undefined' && module.exports) module.exports = XEXPORTREPORT; | |
| else window.XEXPORTREPORT = XEXPORTREPORT; | |
| </script> | |
| <script> | |
| (function(){ | |
| var src=document.getElementById('src'), out=document.getElementById('out'), go=document.getElementById('go'), today=document.getElementById('today'); | |
| today.value=new Date().toISOString().slice(0,10); | |
| function run(){ try { var res=window.XEXPORTENGINE.engine.check(src.value,{today:today.value}); out.innerHTML=window.XEXPORTREPORT.toHtml(res); } catch(e){ out.innerHTML='<p class="sev error">Could not run: '+String(e.message||e)+'</p>'; } } | |
| go.onclick=run; if (src.value.trim()) run(); | |
| })(); | |
| </script> | |
| <section data-yj-install="free" style="margin:2rem auto 1rem;max-width:46rem;padding:1.25rem 1.25rem;border:1px solid #cfe3d6;border-radius:12px;background:#f6fbf8;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .4rem;font-size:1.2rem">Install free</h2><p style="margin:0 0 .8rem;color:#41505f">Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.</p><a href="https://open-vsx.org/extension/readystack/crypto-export-notice-lint" rel="noopener" data-yj-install-door="ovsx" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'crypto-export-notice-lint',src:'ovsx',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Open VSX (Cursor, VSCodium)</a><a href="https://www.npmjs.com/package/@readystack/crypto-export-notice-lint" rel="noopener" data-yj-install-door="npm" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'crypto-export-notice-lint',src:'npm',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">npm</a><a href="https://www.npmjs.com/package/@readystack/crypto-export-notice-lint" rel="noopener" data-yj-install-door="mcp" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'crypto-export-notice-lint',src:'mcp',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">MCP server (npx)</a><a href="https://hub.docker.com/r/getreadystack/crypto-export-notice-lint" rel="noopener" data-yj-install-door="docker" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'crypto-export-notice-lint',src:'docker',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Docker Hub</a><pre style="margin:.5rem 0 0;padding:.6rem .8rem;background:#f3f5f8;border-radius:8px;font-size:.9rem;overflow:auto">npx @readystack/crypto-export-notice-lint <file> | |
| npx @readystack/crypto-export-notice-lint --mcp | |
| docker run --rm -v "$PWD:/w" getreadystack/crypto-export-notice-lint /w</pre><p style="margin:.6rem 0 0;font-size:.92rem;color:#41505f"><a href="https://getreadystack.com/api/buy/cl/polar_cl_l6iN1uWt0FwWu7tBsczD0jWpP2vxFM54Wdwqb3KPi1G" rel="nofollow" style="color:#0f7b3f;text-decoration:underline">Team? One key for every ReadyStack linter, 5 seats, $149 once</a></p></section> | |
| <section data-yj-alert="rule" style="margin:1rem auto 1.5rem;max-width:46rem;padding:1.1rem 1.25rem;border:1px solid #d9dee6;border-radius:12px;background:#fbfcfd;font:15px/1.55 system-ui,-apple-system,Segoe UI,sans-serif"><b style="font-size:1.05rem">Get the full rule table as a PDF</b><div style="opacity:.78;margin:.35rem 0 .8rem">All 10 rules Crypto Export Notice Lint (EAR 742.15) checks, each with its source and date, on printable pages you can hand to your team or auditor. We email it now, and once more only if a rule changes. No newsletter.</div><div style="display:flex;gap:8px;flex-wrap:wrap"><input id="yjae" type="email" placeholder="you@example.com" style="flex:1;min-width:210px;padding:11px 13px;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:#fff;color:inherit"><button id="yjab" style="padding:11px 18px;border-radius:8px;border:0;cursor:pointer;background:#0f7b3f;color:#fff;font:600 15px system-ui,sans-serif">Email me the PDF</button></div><div id="yjao" hidden style="margin-top:.6rem;color:#0f7b3f">Sent. It arrives within the hour - check spam too.</div><script>(function(){var b=document.getElementById("yjab"),e=document.getElementById("yjae");if(!b||!e)return;b.addEventListener("click",function(){var v=e.value.trim();if(!/.+@.+\..+/.test(v))return;try{localStorage.setItem("yj_em","1");}catch(_){}fetch(location.origin+"/api/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:v,slug:"crypto-export-notice-lint",lang:"en",source:"rule_table"+((b.closest&&b.closest("section")&&b.closest("section").getAttribute("data-yj-moved"))?"_at_result":"")})}).then(function(r){var o=document.getElementById("yjao");o.hidden=false;if(!r.ok){o.textContent="Could not save - please try again.";}}).catch(function(){var o=document.getElementById("yjao");o.hidden=false;o.textContent="Could not save - please try again.";});});})();</script><script>(function(){var e=document.getElementById("yjae"),s=e&&e.closest?e.closest("section"):null,o=document.getElementById("out");if(!s||!o)return;var d=false;function mv(ev){if(d)return;if(ev&&ev.target&&s.contains(ev.target))return;d=true;var b=o;while(b.parentNode&&b.parentNode!==document.body&&b.parentNode.tagName!=="MAIN"&&b.parentNode.tagName!=="ARTICLE")b=b.parentNode;if(!b.parentNode||b===s||b.contains(s))return;try{b.parentNode.insertBefore(s,b.nextSibling);s.setAttribute("data-yj-moved","1");}catch(_){}}document.addEventListener("input",mv,true);document.addEventListener("change",mv,true);})();</script></section> | |
| <section data-yj-cta="paid" style="margin:3rem auto;max-width:46rem;padding:1.5rem 1.25rem;border:1px solid #d8dee9;border-radius:12px;background:#fbfcfe;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .5rem;font-size:1.25rem">Get the complete version <span class="yj-price">$29</span></h2><p style="margin:.25rem 0 1rem;color:#41505f">This page is the working piece. The full pack has everything below.</p><p style="margin:0 0 1rem;color:#41505f">Ten checks on the export paragraph of a repository that ships encryption</p><p style="margin:0 0 1rem;color:#5b6b7c;font-size:.94rem">US export-control counsel is commonly quoted at 300-600 USD per hour, and a release review is not billed in minutes.</p><a href="https://getreadystack.com/api/buy/cl/polar_cl_Lc28mhKuKp4eH5tAgxzJQMaxWtH5MmoVxlIvk03slmO" rel="nofollow" style="display:inline-block;padding:.7rem 1.3rem;border-radius:8px;background:#1b64f2;color:#fff;text-decoration:none;font-weight:600">Buy the full version — $29</a></section> | |
| <!--yj-share-s101--><div style="margin:28px 0 8px;text-align:center"><button id="yjcp" type="button" style="font:inherit;padding:10px 18px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Copy link</button><button id="yjimg" type="button" style="font:inherit;padding:10px 18px;margin-left:8px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Save result as image</button></div><script>(function(){var b=document.getElementById("yjimg");if(!b)return;b.addEventListener("click",function(){var o=document.getElementById("out");var txt=(o&&(o.innerText||o.textContent)||"").trim();if(!txt){b.textContent="(no result yet)";setTimeout(function(){b.textContent="Save result as image";},1500);return;}var lines=txt.split(String.fromCharCode(10)).filter(function(x){return x.trim();}).slice(0,10);var W=1200,P=56,c=document.createElement("canvas");c.width=W;var lh=38,H=P*2+70+lines.length*lh+60;c.height=H;var x=c.getContext("2d");x.fillStyle="#1a1512";x.fillRect(0,0,W,H);x.fillStyle="#f3e9d2";x.font="600 34px system-ui,Segoe UI,Arial";var t=(document.title||"").split("|")[0].trim();x.fillText(t.slice(0,54),P,P+34);x.font="22px ui-monospace,Menlo,Consolas,monospace";x.fillStyle="#e8dcc4";for(var i=0;i<lines.length;i++){x.fillText(lines[i].slice(0,88),P,P+70+i*lh+22);}x.font="600 22px system-ui,Segoe UI,Arial";x.fillStyle="#c9a227";var d=location.hostname.replace("www.","");x.fillText(d,W-P-x.measureText(d).width,H-P+6);c.toBlob(function(bl){var u=URL.createObjectURL(bl),a=document.createElement("a");a.href=u;a.download=(t||"result").replace(/[^a-z0-9]+/gi,"-").toLowerCase()+"-"+d+".png";document.body.appendChild(a);a.click();setTimeout(function(){URL.revokeObjectURL(u);a.remove();},2000);},"image/png");});})();</script><script>(function(){var b=document.getElementById("yjcp");if(!b)return;var t=b.textContent;b.addEventListener("click",function(){var u=location.href.split("#")[0];function d(){b.textContent="Link copied";setTimeout(function(){b.textContent=t;},1800);}if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(u).then(d,function(){prompt("",u);});}else{prompt("",u);}});})();</script> | |
| <script data-yj="yj-view-beacon">(function(){try{var p=location.pathname;var k='yjv:'+p;if(sessionStorage.getItem(k))return;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",ref:(document.referrer||''),src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}catch(e){}})();</script> | |
| <script data-yj="yj-use-beacon">(function(){try{var o=document.getElementById('out');if(!o)return;var p=location.pathname,k='yju:'+p,sent=false;function fire(){if(sent||sessionStorage.getItem(k))return;if(!(o.textContent||'').replace(/\s+/g,'').length)return;sent=true;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",t:'use',src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}var mo=new MutationObserver(function(){fire();if(sent)mo.disconnect();});mo.observe(o,{childList:true,characterData:true,subtree:true});}catch(e){}})();</script><div class="yj-home-find"><div class="yj-lgbar"><a href="/" class="yj-lg on">EN</a><a href="/de/" class="yj-lg">DE</a><a href="/ja/" class="yj-lg">JA</a><a href="/es/" class="yj-lg">ES</a><a href="/pt/" class="yj-lg">PT</a></div><section class="yj-find"><h2>Find a tool</h2><input id="yjq" type="search" autocomplete="off" placeholder="Type a product name, format or task"><div id="yjr"></div></section><style>.yj-lgbar{position:absolute;top:14px;right:18px;display:flex;gap:6px;z-index:60}.yj-lg{font:600 12px/1 system-ui,sans-serif;padding:6px 9px;border-radius:4px;text-decoration:none;color:#8b96a3;border:1px solid rgba(140,150,165,.28)}.yj-lg:hover{color:#e8eaed;border-color:rgba(160,175,195,.6)}.yj-lg.on{color:#0e1116;background:#cfd6de;border-color:#cfd6de}.yj-find{max-width:760px;margin:34px auto 8px;padding:0 20px}.yj-find h2{font:600 20px/1.3 system-ui,sans-serif;margin:0 0 10px}#yjq{width:100%;box-sizing:border-box;padding:13px 15px;font:400 15.5px system-ui,sans-serif;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:rgba(255,255,255,.04);color:inherit}#yjq:focus{outline:none;border-color:#7FD1C4}#yjr{margin-top:10px;display:flex;flex-direction:column;gap:6px}#yjr a{display:flex;justify-content:space-between;gap:12px;padding:11px 14px;border:1px solid rgba(140,150,165,.22);border-radius:6px;text-decoration:none;font:400 14.5px/1.4 system-ui,sans-serif;color:inherit}#yjr a:hover{border-color:#7FD1C4}#yjr .pr{font:600 13px system-ui,sans-serif;color:#5fbf9a;white-space:nowrap}</style><script>(function(){var q=document.getElementById("yjq"),r=document.getElementById("yjr"),D=null;function load(){if(D)return Promise.resolve(D);return fetch("/search-index.json").then(function(x){return x.json();}).then(function(j){D=j;return j;}).catch(function(){D=[];return D;});}function esc(t){return String(t).replace(/[&<>"]/g,function(c){return {"&":"&","<":"<",">":">",'"':"""}[c];});}function run(){var v=q.value.trim().toLowerCase();if(v.length<2){r.innerHTML="";return;}load().then(function(j){var w=v.split(/\s+/),o=[];for(var i=0;i<j.length&&o.length<12;i++){var t=j[i].t.toLowerCase();var ok=true;for(var k=0;k<w.length;k++){if(t.indexOf(w[k])<0){ok=false;break;}}if(ok)o.push(j[i]);}r.innerHTML=o.length?o.map(function(x){return "<a href=\""+esc(x.u)+"\">"+"<span>"+esc(x.t)+"</span>"+(x.p?"<span class=\"pr\">$"+x.p+"</span>":"")+"</a>";}).join(""):"";});}q.addEventListener("input",run);q.addEventListener("focus",load);})();</script></div><section data-yj="yj-facts-v1" style="max-width:920px;margin:48px auto 0;padding:0 20px;font-family:system-ui,sans-serif"><style>.yj-article p{font:400 15.5px/1.7 system-ui,sans-serif;color:#26313b;margin:0 0 12px;max-width:72ch}.yj-article h2,.yj-article h3,.yj-article h4{font:600 17px/1.35 system-ui,sans-serif;color:#1b1f24;margin:22px 0 8px}.yj-article table{border-collapse:collapse;margin:10px 0 16px;font:14px/1.45 system-ui,sans-serif}.yj-article th,.yj-article td{border:1px solid #e2e6ea;padding:6px 10px;text-align:left}.yj-article th{background:#f4f6f8}.yj-article pre{background:#0f1720;color:#e6edf3;padding:12px 14px;border-radius:8px;overflow:auto;font:13px/1.5 ui-monospace,Menlo,monospace}.yj-article code{font:13px ui-monospace,Menlo,monospace;background:#f1f3f5;padding:1px 4px;border-radius:3px}.yj-article pre code{background:none;padding:0}.yj-article ul,.yj-article ol{font:15px/1.6 system-ui,sans-serif;color:#26313b}</style><p style="font:400 13px/1.5 system-ui,sans-serif;color:#6b7680;margin:0 0 14px"><time datetime="2026-09-22">Updated 2026-09-22</time> · ReadyStack</p><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","dateModified":"2026-09-22","author":{"@type":"Organization","name":"ReadyStack"}}</script><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Worked example</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 16px;color:#5b6570">Real numbers from this tool, line by line.</p><div class="yj-article"><p><img src="https://getreadystack.com/img/promo/sku164614_result_card.jpg" alt="Crypto Export Notice Lint (EAR 742.15)" loading="lazy" style="max-width:100%;border-radius:6px"></p> | |
| <p>Six of ten export checks failed on one ordinary open-source notice, on a US-published secrets vault. The code was fine; the paragraph under "Export notice" was not.</p> | |
| <p>That paragraph is where the US export rule actually lands. When you publish encryption source code from the United States, EAR 742.15(b) does not ask about your cipher suite. It asks whether you emailed the internet location of that source to crypt@bis.doc.gov and to enc@nsa.gov, and it asks again whenever that location changes. The public-availability position most maintainers rely on is conditioned on that email, and the notice in the repository is usually the only record that it ever went out.</p> | |
| <p>Here is the notice we ran, shortened but otherwise as written:</p> | |
| <p>"This project is publicly available open source, so it is not subject to the EAR and no export licence is required to download it. We publish the source under License Exception TSU (EAR 740.13(e)) and treat the package as EAR99 for customs paperwork. The notification email was sent to crypt@bis.doc.gov on 2019-03-04."</p> | |
| <p>Ten checks ran against it. Six came back, four errors and two warnings:</p> | |
| <ol><li>"Not subject to the EAR." Public availability under 742.15(b) is conditioned on the notification. A licence file does not grant it.</li></ol> | |
| <ol><li>"License Exception TSU (EAR 740.13(e))." BIS removed that paragraph in the encryption rule of 20 September 2016 and moved the notification to 742.15(b). It is the most copied sentence in open-source export notices, out of date for ten years.</li></ol> | |
| <ol><li>"EAR99." EAR99 is not a classification for encryption source code. An ECCN such as 5D002 is.</li></ol> | |
| <ol><li>crypt@bis.doc.gov with no enc@nsa.gov. The ENC Encryption Request Coordinator sits in the same sentence of the rule as BIS, and it is the address that gets dropped.</li></ol> | |
| <ol><li>A notification dated 2019-03-04, which is 2758 days before the day we ran the check, 2026-09-21. Everything published since then stands behind an email about a URL from seven years ago.</li></ol> | |
| <ol><li>No line saying a fresh notification goes out when the source moves. Repositories get renamed and mirrored, and the rule follows the location.</li></ol> | |
| <p>The clean notice shipped beside it, with both addresses, ECCN 5D002, a dated notification and a re-notify sentence, returns zero findings. The distance between the two files is about six lines of text.</p> | |
| <p>Why not ask an assistant? Because the sentence an assistant hands you is sentence two above. Models reproduce the text they learned, and the pre-2016 phrasing is far more common online than the current one. More to the point, no chatbot can read the date sitting in your own notice, count 2758 days against today, and tell you which releases that email failed to cover. That is a job for something that reads your file.</p> | |
| <p>Crypto Export Notice Lint is a VS Code extension and a single web page running one engine, byte for byte the same. Free and without a key: all ten checks on the notice open in the editor, marked line by line in the Problems panel, no run limit, no network call. The licensed part is a different job rather than a smaller one, on the scope and ownership axis: sweep every Markdown file in the repository and write a dated report file you keep and hand to whoever asks for it. That sweep is free for seven days from the first time you run it.</p> | |
| <p>The yardstick is easy to name. US export-control counsel is commonly quoted at 300-600 USD per hour, and a release review is not billed in minutes.</p> | |
| <p>The calendar does not stop at the email: maintainers on the mass-market encryption paths also owe an annual self-classification report by 1 February for what shipped the year before. The export paragraph is where that trail starts.</p></div><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:30px 0 10px;color:#1b1f24">15 seconds — what it actually does</h2><video controls muted playsinline preload="none" poster="/img/promo/sku164614_result_card.jpg" style="width:100%;max-width:360px;border-radius:10px;display:block;margin:0 auto"><source src="/media/sku164614_short.mp4" type="video/mp4"></video><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:34px 0 6px;color:#1b1f24">Questions people ask</h2><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What does this actually do?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">It reads the export-control paragraph in your Markdown — README, EXPORT, NOTICE, SECURITY — and reports which of ten documented items are absent or wrong: the crypt@bis.doc.gov and enc@nsa.gov addresses, the published source URL, an ECCN such as 5D002, the notification date, the removed 740.13(e) citation, and the line about re-notifying when the source moves.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Who is it for?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Maintainers and founders who publish source code containing encryption from the United States: the person who tags a release of a password manager, an end-to-end messaging client, a database with encryption at rest, or an SDK that wraps libsodium or OpenSSL. Also the security engineer who inherits that repository and its export paragraph.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Why will a free chatbot not do this?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Because the paragraph most assistants reproduce cites License Exception TSU at EAR 740.13(e), which BIS removed in the encryption rule of 20 September 2016 and replaced with the notification in 742.15(b). A generative answer restates the text it learned; it cannot tell you that your own notice is dated 2019 and missing enc@nsa.gov.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What is free and what needs a key?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Checking the file open in your editor against all ten checks is free forever, with no key, no watermark and no run limit. The licence key covers a different axis: sweeping every Markdown file in the repository and writing a dated report file you own. That sweep also runs free for its first seven days.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What did it find on the sample notice?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Six findings on one ordinary-looking export paragraph — four errors and two warnings: no enc@nsa.gov, no ECCN, a removed 740.13(e) citation, an EAR99 claim, a notification dated 2019-03-04 and no re-notify line. The clean notice shipped beside it returns zero. US export-control counsel is commonly quoted at 300-600 USD per hour.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Why not just ask ChatGPT or another AI chat?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. Crypto Export Notice Lint (EAR 742.15) checks the file you open against 10 rules from a rule set dated 2026-09-21, and points at the exact line. For a filing, an audit or a client you need that dated result on your own files.</p></details><script type="application/ld+json" data-yj="yj-faq-ld">{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "What does this actually do?", "acceptedAnswer": {"@type": "Answer", "text": "It reads the export-control paragraph in your Markdown — README, EXPORT, NOTICE, SECURITY — and reports which of ten documented items are absent or wrong: the crypt@bis.doc.gov and enc@nsa.gov addresses, the published source URL, an ECCN such as 5D002, the notification date, the removed 740.13(e) citation, and the line about re-notifying when the source moves."}}, {"@type": "Question", "name": "Who is it for?", "acceptedAnswer": {"@type": "Answer", "text": "Maintainers and founders who publish source code containing encryption from the United States: the person who tags a release of a password manager, an end-to-end messaging client, a database with encryption at rest, or an SDK that wraps libsodium or OpenSSL. Also the security engineer who inherits that repository and its export paragraph."}}, {"@type": "Question", "name": "Why will a free chatbot not do this?", "acceptedAnswer": {"@type": "Answer", "text": "Because the paragraph most assistants reproduce cites License Exception TSU at EAR 740.13(e), which BIS removed in the encryption rule of 20 September 2016 and replaced with the notification in 742.15(b). A generative answer restates the text it learned; it cannot tell you that your own notice is dated 2019 and missing enc@nsa.gov."}}, {"@type": "Question", "name": "What is free and what needs a key?", "acceptedAnswer": {"@type": "Answer", "text": "Checking the file open in your editor against all ten checks is free forever, with no key, no watermark and no run limit. The licence key covers a different axis: sweeping every Markdown file in the repository and writing a dated report file you own. That sweep also runs free for its first seven days."}}, {"@type": "Question", "name": "What did it find on the sample notice?", "acceptedAnswer": {"@type": "Answer", "text": "Six findings on one ordinary-looking export paragraph — four errors and two warnings: no enc@nsa.gov, no ECCN, a removed 740.13(e) citation, an EAR99 claim, a notification dated 2019-03-04 and no re-notify line. The clean notice shipped beside it returns zero. US export-control counsel is commonly quoted at 300-600 USD per hour."}}, {"@type": "Question", "name": "Why not just ask ChatGPT or another AI chat?", "acceptedAnswer": {"@type": "Answer", "text": "A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. Crypto Export Notice Lint (EAR 742.15) checks the file you open against 10 rules from a rule set dated 2026-09-21, and points at the exact line. For a filing, an audit or a client you need that dated result on your own files."}}]}</script><div id="yj-ask" style="margin:36px 0 0;padding:18px 18px 16px;border:1px solid #e2e6ea;border-radius:10px;background:#fbfbfc"><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:0 0 4px;color:#1b1f24">Ask about this tool</h2><p style="font:400 13.5px/1.5 system-ui,sans-serif;margin:0 0 12px;color:#5b6570">One question, answered by the person who built it. Your email only if you want the answer sent.</p><form onsubmit="return yjAsk(event)" style="display:grid;gap:8px"><textarea name="question" required minlength="10" maxlength="2000" rows="3" placeholder="Your question" style="font:14px/1.5 system-ui,sans-serif;padding:10px;border:1px solid #cfd6dd;border-radius:6px"></textarea><div style="display:flex;gap:8px;flex-wrap:wrap"><input type="email" name="email" placeholder="Email (optional)" style="flex:1;min-width:200px;font:14px system-ui,sans-serif;padding:9px 10px;border:1px solid #cfd6dd;border-radius:6px"><button type="submit" style="font:600 14px system-ui,sans-serif;padding:9px 18px;border:0;border-radius:6px;background:#1b1f24;color:#fff;cursor:pointer">Send</button></div><p id="yj-ask-msg" style="font:13px system-ui,sans-serif;margin:2px 0 0;color:#0a6238;min-height:1em"></p></form><script>function yjAsk(e){e.preventDefault();var f=e.target,m=document.getElementById("yj-ask-msg");m.style.color="#0a6238";fetch(location.origin+"/api/ask",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sku:164614,slug:"crypto-export-notice-lint",lang:"en",question:f.question.value,email:f.email.value,page:location.pathname})}).then(function(r){if(!r.ok)throw 0;m.textContent="Thanks \u2014 noted. Answers land on this page and, if you left an email, in your inbox.";f.question.value="";}).catch(function(){m.style.color="#a8551f";m.textContent="Could not send. Please try again in a minute.";});return false;}</script></div></section><section class="yj-related" style="max-width:920px;margin:56px auto 40px;padding:0 20px"><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Same job, next tool</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 20px;color:#5b6570">Free in the browser. The full version is a one-time licence.</p><div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px"><a class="yj-rel-c" href="https://getreadystack.com/tools/autohotkey-toml-devicetree-snippets"><span class="yj-rel-t">AutoHotkey v2, TOML and DeviceTree checks for VS Code</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/firestore-rules-guard"><span class="yj-rel-t">Firestore Rules Guard</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/bulk-sender-lint"><span class="yj-rel-t">Bulk Sender Lint - the Gmail, Yahoo and Outlook.com rules, checked in your mai</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/coppa-notice-lint-2026"><span class="yj-rel-t">COPPA 2026 Notice Lint</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/csaf-advisory-check-cra-2026"><span class="yj-rel-t">CSAF Advisory Check for CRA 2026</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/coverage-gate-lint"><span class="yj-rel-t">Coverage Gate Lint</span><span class="yj-rel-p">$29</span></a></div><style>.yj-rel-c{display:flex;flex-direction:column;gap:8px;padding:15px 16px;border:1px solid #e2e6ea;border-radius:6px;text-decoration:none;background:#fff}.yj-rel-c:hover{border-color:#b9c2cb;background:#fafbfc}.yj-rel-t{font:500 14.5px/1.42 system-ui,sans-serif;color:#1b1f24}.yj-rel-p{font:600 13px system-ui,sans-serif;color:#0a6238}</style></section></body> | |
| </html> | |