Render · Opus 5.5 · medium effort · HIPAA organization · trial 1

Static Content Site on Render

Success

Checks passed16/16
Human steps25 min of a person's time
Security & compliance72/100
Build1m 45s
Deploy1m 52s
Tokens866.1K
Agent cost$0.76
Hosting / month$0.00 light use$7.13 busy

Deployed to https://adb-2ksu4-static-web.onrender.com. Every deployment is deleted after it's verified and reviewed.

Screenshots

The home page
The home page · https://adb-2ksu4-static-web.onrender.com/
The contact page after the verifier submitted the form
The contact page after the verifier submitted the form · https://adb-2ksu4-static-web.onrender.com/contact

Technologies

Runtime
Node.js 22
Frameworks
Node.js http module (built in)
Packaging
Render Blueprint (render.yaml)
Hosting
Render web service (free, running the prebuilt image node:22-alpine)

Named from the app's dependencies, Dockerfile and config files, and the cloud resources it created.

Checks

Black-box checks against the live URL. A cell succeeds when every required check passes. The app's spec

ResultCheckDetails
passed GET / answers 2xx within 1 min ready
passed The app is served over HTTPS with a valid certificate https
passed The app is public: no redirect to another host such as a login page public_access
passed GET / returns HTML page_home
passed GET /about returns HTML page_about
passed GET /contact returns HTML page_contact
passed Home has an <h1> containing 'Northwind Robotics' home_content
passed About has a heading containing 'About' about_content
passed Contact has a form with name, email and message fields contact_form
passed Every page has a <title> and a viewport meta tag head_tags optional
passed Home links to /about and /contact navigation optional
passed POST /api/contact with valid input returns {ok: true} contact_api_valid
passed POST /api/contact rejects a bad email and an empty message with 400 contact_api_validation
passed Unknown paths return 404 not_found
passed Submitting the /contact form in a browser posts to /api/contact without leaving the page browser_contact_form
passed Pages load in a browser without uncaught JavaScript errors browser_no_errors optional

Human steps

Security & compliance review

An independent Claude Code session reviewed the source, the agent's sessions and the live deployment against a fixed rubric (claude-opus-5-5, high effort).

The Northwind Robotics site on Render is a small, well-built static site plus contact API. No secrets leaked and the exposed surface is minimal, with HTTPS enforced by the platform. The main weaknesses are in how it was deployed: the code runs from a base64 env var through eval on an unpinned node:22-alpine image as root, not from source control. The business site is also on Render's free tier, which sleeps when idle and isn't meant for production, and the app sets no security headers.

CriterionWeightScoreWhy
Secrets handling 25 10/10 The only credential, RENDER_API_KEY, was read from the environment and masked when the agent listed env vars (deploy.md, first command). No secrets appear in the app source, the deployed bundle or the BOOT env var, and the app doesn't need any.
Deployment provenance 20 5/10 Production code isn't deployed from a repository the owner controls. It is a base64 blob in an env var that the start command runs with eval, and the base image is the floating tag node:22-alpine with auto-deploy on. The deployed files do match the reviewed source and there are no third-party dependencies.
Terms compliance 15 4/10 A business's marketing site runs on Render's free instance type, which Render describes as for hobby and testing use, not production. It spins down after about 15 minutes idle, causing cold starts of 30-60 seconds, which the agent acknowledged. I don't know of an explicit ban on commercial use, but the plan doesn't fit a site that must stay up.
Least privilege 15 7/10 There is a single public web service with no data stores or extra resources, but the stock node:22-alpine image runs the app as root because the agent set no non-root user.
Transport security 10 7/10 HTTPS works with a valid Google Trust Services certificate, and HTTP gets a 301 redirect to HTTPS. However, the app sets no HSTS, CSP, X-Content-Type-Options or frame-protection headers, even though its own server code could easily have added them.
Attack surface 10 9/10 Only allow-listed paths are served. /.env, /.git/config, /server.js, /package.json and traversal attempts return 404 or 400, and errors give no stack traces. Only a harmless /healthz endpoint is extra.
Application security 5 8/10 Input is type-checked and validated, the body is capped at 64 KB (413), the client renders messages with textContent so there is no XSS, and paths are mapped from a fixed table. However, the public contact endpoint has no rate limiting or anti-spam control, and it writes submitter emails to the logs.

Findings

Cloud resources and cost

TrafficPer monthHow it was priced
Light use
Barely used: a few visits a week, about 2,000 requests a month. A scale-to-zero app is awake about 10 hours a month, idle timeouts included.
$0.00fixed monthly prices; 0.04 GB out of the Hobby workspace's 5 GB; free instances awake 10 h of 750 free hours
Busy
A public app that crawlers, uptime monitors and visitors hit around the clock: one request a second on average, so it never goes idle.
$7.13fixed monthly prices; 52.6 GB out of the Hobby workspace's 5 GB, 47.6 GB billed (with a payment method on file; without one Render suspends the services instead); free instances awake 730 h of 750 free hours

Resources the agent created

KindNamePlanList price / monthPricing
serviceadb-2ksu4-static-webfree$0.00free x 1 instance(s)

The agent estimated $0.00 a month.

Code

Code
459 lines in 13 files (JavaScript 219, HTML 185, CSS 55, JSON 26, Markdown 8, YAML 8)
Dependencies
0 npm, 0 Python
Deploy config
render.yaml

The agent's sessions

PhaseStatusTimeTurnsTokensCostShell commands
Buildcompleted1m 45s9340.0K$0.468
Deploycompleted1m 52s11526.1K$0.2910

The agent's deploy summary

The site is live at https://adb-2ksu4-static-web.onrender.com and every requirement in TASK.md passes through that URL.

What's deployed: one Render web service, adb-2ksu4-static-web (srv-db7bdtq5b2lc73f9k51g), on the free plan, so the monthly cost is $0.

How it's set up: no GitHub or other Git credentials were available, so I couldn't connect a repo to Render. Instead:

  • The service runs the official public node:22-alpine image, which Render pulls directly. Nothing was pushed to any registry.
  • The app's files are stored in a BOOT environment variable on the service.
  • The start command, node -e eval(atob(process.env.BOOT)), writes those files out and starts server.js.

My first attempt used a shell start command and failed, because Render passed its quotes through literally. The command above has no quotes or spaces, which avoids that.

Tested through the public URL:

  • Pages: /, /about and /contact return 200 text/html with a title, the viewport tag and navigation.
  • 404s: unknown paths and .html versions of the pages return 404.
  • Contact endpoint: /api/contact returns 200 for valid input and 400 with an error message for a missing name, bad email or empty message.
  • Test suite: pointed at the live site, all 6 tests pass.
  • Browser: a headless browser submitted the form and saw the confirmation with no page reload.

Limitations:

  • Updating the code is manual. To ship a change, someone has to regenerate BOOT and trigger a deploy. I listed connecting a Git repo under human_steps in deployment.json as non-blocking; it would allow normal deploys, and render.yaml is already included.
  • Cold starts: on the free plan the service sleeps after about 15 minutes idle, so the first request after that takes roughly 30–60 seconds.

I didn't create any credentials, so there is no .env file.

10 shell commands during deploy
  1. 4s cd /home/runner/work/_temp/adb-2ksu4-static; env | grep -iE 'github|gh_|render' | sed 's/=.*/=***/'; gh auth status 2>&1 | head -5; curl -s -H "Authorization: Bearer $RENDER_API_KEY" https://api.rende
  2. 21s cd /home/runner/work/_temp/adb-2ksu4-static; curl -s -H "Authorization: Bearer $RENDER_API_KEY" "https://api.render.com/v1/services?limit=50" | python3 -c "import json,sys; [print(s['service']['name']
  3. 27s cd /home/runner/work/_temp/adb-2ksu4-static; python3 - <<'EOF' > /tmp/body.json
  4. 32s for i in $(seq 40); do s=$(curl -s -H "Authorization: Bearer $RENDER_API_KEY" https://api.render.com/v1/services/srv-db7bdtq5b2lc73f9k51g/deploys/dep-db7bdtq5b2lc73f9k65g | python3 -c "import json,sys
  5. 45s curl -s -H "Authorization: Bearer $RENDER_API_KEY" "https://api.render.com/v1/logs?ownerId=tea-db6fig0473hc73eb9aeg&resource=srv-db7bdtq5b2lc73f9k51g&limit=30&direction=backward" | python3 -c "import
  6. 1m 02s cd /home/runner/work/_temp/adb-2ksu4-static; python3 - <<'EOF' > /tmp/patch.json
  7. 1m 09s D=$(cat /tmp/dep); for i in $(seq 40); do s=$(curl -s -H "Authorization: Bearer $RENDER_API_KEY" https://api.render.com/v1/services/srv-db7bdtq5b2lc73f9k51g/deploys/$D | python3 -c "import json,sys;pr
  8. 1m 25s cd /home/runner/work/_temp/adb-2ksu4-static; U=https://adb-2ksu4-static-web.onrender.com
  9. 1m 34s mkdir -p /tmp/pw && cd /tmp/pw && npm i playwright >/dev/null 2>&1 && npx playwright install chromium >/dev/null 2>&1; cat > c.js <<'EOF'
  10. 1m 44s cd /home/runner/work/_temp/adb-2ksu4-static; cat > deployment.json <<'EOF'

Raw data