Docs · Security
How components are checked
Every component in the library is written for Fieldbook, and every one goes through the same gates before it ships: a type check, a lint pass, a native render in a headless browser, the anti-slop score, and a static security scan over all of its files (tsx, vue, svelte, astro, html and css). The scan executes nothing; it reads text and matches known-unsafe patterns. The result is stored on the component and shown on its determination label.
The three verdicts
Each rule carries a severity. A variant’s verdict is the worst severity that fired across all its files; nothing averages away a single serious finding.
- flaggedany block-severity rule: A blocking finding, the security equivalent of a hard fail.
- reviewa warn rule, no block: Worth a human glance before you paste it in.
- cleanonly info rules, or nothing: Noted for context: expected, normal behaviour.
Red is used for a flagged verdict only, the same discipline the rest of the site follows: red marks a hard failure and nothing softer.
What the scan looks for
Ruleset 2026.09.1, 34 rules. Highlights: dynamic code evaluation (eval, new Function, a code string in a timer); HTML injection sinks (innerHTML/outerHTML/insertAdjacentHTML, React dangerouslySetInnerHTML, Vue v-html, Svelte {@html}) fed a non-literal value; remote script, iframe and stylesheet injection (well-known CDNs noted as informational); network calls to unrecognized hosts; reads of tokens from cookies or storage; postMessage to "*"; obfuscation signals (long base64 or hex-escaped blobs, atob(unescape(…)), fromCharCode chains); hardcoded credentials and secret-shaped env reads; camera / mic / geolocation / service-worker requests; and prototype-pollution patterns.
atob-decodeinfo → cleanatob on its own is benign (decoding an image or a small blob). Flagged as info so a reviewer can confirm it is not the first step of an obfuscated payload.
base64-blobinfo → cleanA large base64 string is usually an inlined image or font, but can also be a concealed script. Info so a reviewer can glance at what it decodes to.
clipboard-writeinfo → cleanCopy-to-clipboard is a normal UI affordance. Info only, so a reviewer is aware the component can set clipboard contents.
cookie-readwarn → reviewThe cookie jar usually holds session identifiers. A UI component has no reason to read it; when it does, a reviewer should confirm where the value goes.
crypto-miningblock → flaggedNames of known browser crypto-miners. A component that pulls in a miner steals a visitor's CPU. There is no benign reason for these strings to appear.
document-writewarn → reviewdocument.write injects markup into the page as it parses and is a common vehicle for smuggling in remote scripts. Modern components never need it.
env-secretwarn → reviewA client component reading process.env.*_KEY / *_SECRET risks baking a server secret into shipped JS. Surfaced so a reviewer can confirm the value is public (NEXT_PUBLIC_) or server-only.
evalblock → flaggedeval executes an arbitrary string as code, defeating every static guarantee about what the component does. A pasted component that calls eval can run anything the page can.
exfil-sinkblock → flaggedConcatenating cookies or storage into a URL, image source, beacon or socket is the classic credential-exfiltration shape. Blocked outright.
geolocationwarn → reviewReading the visitor's location is a privacy-sensitive capability that most UI components have no need for. Warn so its use is deliberate.
hardcoded-secretblock → flaggedA live-looking API key, GitHub token, AWS access key id, or private key committed into component source. Even if a placeholder, it must not ship in the catalog.
hex-obfuscationwarn → reviewA long run of \xNN escapes hides a string's contents from anyone reading the source. It is a strong signal of a deliberately concealed payload.
innerhtml-dynamicwarn → reviewAssigning a variable or interpolated string to innerHTML/outerHTML/insertAdjacentHTML/dangerouslySetInnerHTML renders it as live HTML. If any part comes from data or props it is an XSS sink.
innerhtml-literalinfo → cleanA plain string constant assigned to innerHTML carries no external input, so it cannot be an injection point. Noted for completeness, not a concern.
media-capturewarn → reviewgetUserMedia / getDisplayMedia turn on the camera, mic, or screen capture. A high-consequence capability that must be intentional, not a hidden side effect of a widget.
network-externalwarn → reviewfetch / XMLHttpRequest / WebSocket / sendBeacon to an external origin sends data off the page. To a host that is not a known public API, it can be exfiltration or unwanted tracking.
network-public-apiinfo → cleanA call to a recognized public, read-only API (GitHub, placeholder image or avatar services, demo JSON). Common in example components; noted, not a concern.
new-functionblock → flaggednew Function(...) compiles a string into executable code, an eval by another name. There is no legitimate reason for a UI component to build functions from strings.
obfuscation-decodewarn → reviewatob(unescape(...)) and long String.fromCharCode(...) chains are classic ways to hide a string from a reader so it can be turned back into code or a URL at runtime. Legitimate components have no reason to obfuscate.
postmessage-wildcardwarn → reviewpostMessage(data, '*') sends the message to whatever origin currently frames the page, so any embedder can read it. Name the target origin instead.
prototype-pollutionwarn → reviewAssigning through __proto__ or constructor.prototype[...] can poison every object in the runtime, a known privilege-escalation and denial-of-service vector. No presentational component needs this.
remote-framewarn → reviewAn <iframe src> to an external origin embeds a page you do not control; it can frame trackers or phishing content. Recognized embed hosts (YouTube, Vimeo) are treated as informational.
remote-frame-cdninfo → cleanAn <iframe src> to a recognized embed host (YouTube, Vimeo). Expected for media components; noted, not a concern.
remote-scriptwarn → reviewA <script src> (or a script element pointed at a URL) loads and runs code from another origin. From a host not on the CDN allowlist, that code is unaudited and can change under you.
remote-script-cdninfo → cleanA <script src> pointed at a well-known CDN (jsdelivr, unpkg, cdnjs, Tailwind play CDN...). Common and expected for html/uiverse specimens; noted, not a concern.
remote-styleinfo → cleanA <link rel=stylesheet> from an external origin can restyle the page and, via url() and font loads, leak referer traffic. Low severity because CSS cannot execute script.
remote-style-cdninfo → cleanA <link rel=stylesheet> from a well-known CDN or the Google Fonts host. Expected; noted, not a concern.
service-workerwarn → reviewA service worker persists in the background and can intercept every request the origin makes, long after the component is gone. Out of scope for a catalog component and worth flagging.
settimeout-stringwarn → reviewsetTimeout/setInterval with a string first argument evaluates that string as code, the same risk as eval. Pass a function instead.
storage-accessinfo → cleanGeneral use of cookies / localStorage / sessionStorage / IndexedDB (e.g. remembering a theme or a dismissed banner). Expected for stateful widgets; noted, not a concern.
storage-tokenwarn → reviewTouching document.cookie / localStorage / sessionStorage / IndexedDB with a token-, auth- or secret-shaped key is how credentials get harvested from a host page. A presentational component should not read them.
svelte-htmlwarn → review{@html expr} injects the expression as raw HTML, bypassing Svelte's escaping. Safe only for values the component itself controls.
vue-htmlwarn → reviewv-html (and an :innerHTML bind) renders the bound expression as raw HTML with no escaping. Bound to anything but a trusted constant it is an XSS sink.
window-openinfo → cleanwindow.open navigates a new tab. Usually benign, but worth surfacing since a hardcoded external URL can be an ad or a redirect. Pair new tabs with rel=noopener.
What it does not promise
This is a static, best-effort screen, not a proof of safety. It reads patterns, not intent: a clean verdict means no known-unsafe pattern was found, not that the component is guaranteed benign. Obfuscation can hide behaviour a text scan cannot see, and a warn verdict is often a perfectly legitimate capability (a copy-to-clipboard button, a fetch to a public API). Always read the source of anything you paste into your project; the MCP tools and the detail page both give you the full code and the list of flags to make that judgement.