At a glance
This page describes Shield’s security posture in concrete detail. Each section answers a question you or your security team are likely to ask. If something is unclear, missing, or feels light, mail security@shieldmycode.com and we’ll respond within one business day.
Account metadata, plan + subscription status, aggregate usage counts, opaque API key hashes, tamper-event reports. Nothing else.
The source code or HTML you submit for obfuscation. The protected output. Your card number. Any data not strictly required to run your account.
DigitalOcean infrastructure (SOC 2 Type II + ISO 27001). Postgres on the same host, encrypted at rest. Nginx + PM2 process management.
Stripe. Card data is collected by Stripe Elements directly inside their hardened iframe — it never touches our server. We see only the last 4 digits and brand.
How we handle your data
Our data minimization is deliberate. Every byte we hold is a byte that could be lost, leaked, or subpoenaed. We hold as little as possible to make Shield work.
Data we store
| What | Detail | Why |
|---|---|---|
| Account identifier | UUID, email, hashed password (bcrypt cost 12), display name, username, optional avatar reference | Authenticate you and address you correctly. |
| Plan & subscription | Plan ID, subscription status, period dates, cancel-at-period-end flag — synced from Stripe via webhooks | Enforce quotas and surface your billing state. |
| Usage metadata | Per-obfuscation: timestamp, kind (JS/HTML), strictness level, byte counts, duration, anonymized 16-char IP hash. Bucketed per (user, calendar month). | Quota accounting and the History view. |
| API key hashes | SHA-256 of the secret portion only. The plaintext key is shown exactly once at creation time. | Authenticate API requests without recoverable storage of secrets. |
| Telemetry events | When you set a telemetry URL: reason code (integrity / debugger / headless / etc.), coarse geo, 16-char IP hash, user-agent substring. Hard-capped at 10,000 events per account; older events evicted automatically. | Power the threat-intel dashboard. |
| GitHub connection | Optional. Your Personal Access Token, encrypted at rest with envelope encryption + AES-256. | GitHub round-trip integration on Pro+ plans. |
| Stripe customer ID | A pointer (cus_...) into Stripe. No card data ever stored on our side. | Tie Shield account to Stripe customer. |
| Session records | Random 64-char session ID, user agent string, anonymized IP hash, last_seen timestamp. Hard expiry 30 days; idle expiry 10 minutes. | Single-session policy enforcement. |
Data we never store
- Source code submitted for obfuscation. Processed in-memory in the obfuscation engine and discarded when the HTTP response completes.
- Obfuscated output. Same path: returned to you in the response, not retained.
- Card numbers, CVCs, expiry dates. Collected by Stripe Elements in a domain-isolated iframe; we receive only a tokenized PaymentMethod ID.
- Plaintext API keys. Hashed at creation; the plaintext appears once on the screen and is then gone forever.
- Plaintext passwords. bcrypt only, never logged.
- Raw IP addresses. Hashed to a 16-character SHA-256 prefix at the moment of capture. The raw IP is not stored or logged.
We do not store your code
This is the question we’re asked most. The answer: source code submitted to Shield is processed in-memory and never written to disk or any database.
Concretely, the lifecycle of a single obfuscation request is:
- HTTPS request arrives at our Nginx reverse proxy
- Proxied to the Node.js process, which parses the JSON body into a JavaScript string in memory
- The obfuscation engine runs synchronously in that process. AST parsing, transforms, defense injection — all in memory.
- The protected output string is JSON-encoded into the HTTP response
- The response is flushed to the network
- The strings are garbage-collected when the request handler returns
Only the metadata of the request — timestamp, kind, level, byte counts, duration, anonymized IP hash, your user ID — is persisted to the audit log table. The source and output bytes are not.
This is verifiable against our source code. The relevant endpoint handlers (e.g. app/api/obfuscate/route.ts) hold the source in a parameter, pass it through the engine, return the result, and do not write it. We are happy to walk through this with your security team on request.
Account & authentication
Passwords
Passwords are hashed using bcrypt at cost factor 12, with a unique per-user salt. The plaintext is never logged or stored. We never compare passwords using string equality; comparisons happen through bcrypt’s timing-safe verification.
Sessions
Login creates a DB-backed session record with a cryptographically random 64-character session ID. AHttpOnly, SameSite=Lax, Secure cookie carries the ID; everything else (user_id, expires_at, user_agent, anonymized ip_hash, last_seen_at) lives in the database. Hard expiry: 30 days. Idle expiry: 10 minutes (rolling — any authenticated request slides the window).
Single-session anti-account-sharing: every successful login deletes all other sessions for that user. Two devices cannot be logged in simultaneously. Designed to deter password sharing across organizations.
GitHub OAuth (optional)
Sign in with GitHub uses OAuth 2.0. We request onlyread:user + user:email scopes — enough to identify and provision accounts, nothing else. The CSRF token is rotated per flow. Your GitHub access token from this flow is exchanged once for the user identity and then discarded. A separate, encrypted PAT is what we store if you opt into the GitHub round-trip integration (Pro+ plans only).
API keys
Each key is a 32-byte random token, base-prefixed withshield_. We store the SHA-256 hash of the secret portion only. The plaintext key is rendered to your browser exactly once — at creation — and then irretrievable. Lost keys cannot be recovered; they must be re-generated. Revoke any time from Dashboard → API keys.
Encryption
In transit
Every public endpoint serves over HTTPS with certificates rotated via Let’s Encrypt’s automated renewal (90-day cycle). Nginx is configured to accept TLS 1.2 and TLS 1.3 only. Strict Transport Security (HSTS) is published with a 6-month max-age and the includeSubDomains directive. Plain HTTP requests are redirected to HTTPS at the proxy layer.
At rest
Disk-level encryption is provided by DigitalOcean’s block-storage service, transparent to the application. Postgres data, Nginx logs, the application code itself, and the env file containing API secrets are all on encrypted volumes.
Application-level encryption is applied to sensitive secrets on top of disk encryption:
- Passwords: bcrypt hash (one-way)
- API keys: SHA-256 hash (one-way)
- GitHub PATs: AES-256-GCM with an envelope key
- Session IDs: not encrypted (entropy is the protection — 256 bits)
In memory
Sensitive values are not logged. The obfuscation engine receives source code strings and discards them when the request completes; we do not write them to stdout, stderr, or the database. Process memory is not deliberately zeroed (Node’s GC handles reclamation), which is a known trade-off documented here for completeness.
Application security
- Input validation: every public API endpoint validates its request body against a Zod schema before any logic runs. Mismatches return a 400 with no further processing.
- CSRF protection: the GitHub OAuth flow rotates a single-use CSRF token via HttpOnly cookie. Stripe checkout calls use session authentication; no cross-site form posts are accepted.
- Rate limiting: the public playground (
/api/try) enforces a per-IP quota (5 obfuscations / hour, 2 / minute, hashed IP). The authenticated APIs are gated by monthly plan quota. - Dependency scanning: GitHub Dependabot is enabled against our main repository. Vulnerable dependencies generate PRs we triage within one business day for high severity.
- Secret management: environment variables live in
/var/www/shield/.env.localon the droplet with file mode0600. Stripe secret key, webhook secret, and GitHub OAuth credentials are never logged. We do not commit secrets to git. - Change management: every code change is in git history with author + timestamp. Deploys are scripted via a versioned installer.
- Backups: Postgres is snapshotted by DigitalOcean’s automated daily backup. Retention: 7 days rolling. Restore tested quarterly.
Infrastructure
Shield runs on a single dedicated DigitalOcean droplet behind Cloudflare-protected DNS, with the following stack:
| Layer | Technology | Role |
|---|---|---|
| DNS | Cloudflare | DDoS protection, TLS edge, request inspection |
| TLS / proxy | Nginx 1.24 | HTTPS termination, gzip, reverse proxy to Node |
| App runtime | Node 20 + Next.js 15 | Application server, obfuscation engine, dashboard |
| Process supervision | PM2 | Restart on crash, log rotation, env injection |
| Database | PostgreSQL 16 | Users, sessions, subscriptions, usage logs, telemetry events, API key hashes |
| Compute | DigitalOcean droplet (Ubuntu 24.04 LTS) | Single-region, encrypted disk, daily snapshot |
Single-region by design: we run in one DigitalOcean region for predictable latency and simpler compliance scope. Multi-region failover is on the Enterprise-tier roadmap.
Subprocessors
These are the third-party services Shield uses to operate. Each is a tier-1 vendor with their own current compliance attestations:
Data shared: Tokenized card / PaymentMethod IDs only — full card numbers never reach Shield. Customer email + name + Stripe customer ID.
Data shared: Everything on the application server, including the Postgres database.
Data shared: HTTP request metadata (no application data passes through unencrypted).
Data shared: Source code is on a private repository. OAuth identity (email + name) for users who sign in with GitHub.
Data shared: Public DNS + ACME challenge data only. No customer or account data.
We do not currently use a transactional email provider, an analytics provider, or a CRM. If we add one, this list will be updated and any change communicated to existing customers with 30 days’ notice.
Compliance & certifications
We are transparent about where we are in the formal compliance lifecycle. Our security posture is mature; formal attestations are an ongoing investment.
No third-party SOC 2 report at this time. The reason is deliberate: Shield’s data minimization (no customer source code stored, payment data offloaded to Stripe) reduces the audit scope dramatically vs typical SaaS, and we’ve prioritized engine + customer experience work that compounds faster. We pursue Type I scoping when a specific enterprise prospect requires it.
EU customers are supported. We act as data processor for any personal data you provide. Data subject access requests can be made via privacy@shieldmycode.com and are answered within 30 days. See Privacy Policy.
California consumers have the same rights of access, deletion, and correction. Sale of personal information: we do not sell.
Card data is collected by Stripe Elements directly in their hardened iframe and never touches our server. Stripe is PCI DSS Level 1 certified. The applicable Stripe SAQ-A pattern means our PCI scope is effectively zero.
Shield does not handle Protected Health Information. We are not currently set up to sign a Business Associate Agreement.
On the same roadmap as SOC 2 — pursued when a specific Enterprise lead requires it.
If your organization requires a specific compliance artifact to evaluate Shield, please contact sales@shieldmycode.com with the requirement and timeline.
Incident response
We follow a documented incident response process. The abbreviated version:
- Detect. Through monitoring, vulnerability disclosure, or customer report.
- Triage. Within one business hour of detection, classify severity (P0 — service down or data exposure; P1 — degraded; P2 — non-urgent).
- Contain. P0 / P1 incidents trigger immediate mitigation (block, rotate, take offline). Where customer credentials may be involved, we invalidate sessions.
- Eradicate & recover. Apply fix, restore service, validate.
- Notify. Affected customers receive direct email notification within 72 hours of incident confirmation. If the incident involves unauthorized access to personal data, we notify regulators where required by GDPR / CCPA.
- Post-mortem. A blameless post-mortem within 14 days of closure, with action items tracked to completion.
Report a vulnerability
We welcome coordinated vulnerability disclosure. If you believe you’ve found a security issue in Shield, please contact us before publishing or sharing details:
- · We acknowledge reports within one business day.
- · Triage and severity assessment within five business days.
- · We will not pursue legal action against good-faith researchers acting under coordinated disclosure.
- · Public credit on this page (with your consent) for valid, in-scope reports.
Out of scope
- Reports purely about missing security headers on marketing pages
- Self-XSS that requires the victim to paste hostile code into their own console
- Social engineering of Shield staff
- DoS / volumetric attacks
- Findings on third-party services (report those to the relevant vendor)
- Theoretical concerns without a reproducible exploit
We do not currently offer a paid bug bounty. We acknowledge publicly and credit researchers who help us in good faith.
Last reviewed: May 2026. This page is versioned in git and updated whenever our posture changes.