Skip to content

Zero-code setup: protect an app without changing it

You can turn on Shield360, telemetry and runtime protection, without editing or rebuilding your app. Settings come from the usual environment variables, and each language has its own way to load the SDK before the app starts.

Every entry point follows three rules:

  • Fails open. If start-up fails, it prints one warning and your app starts anyway.
  • No double start. If the app also calls the SDK’s init in code, that call does nothing and logs one line saying so.
  • Tested end to end with an app that never imports the SDK.

Set these on the process, whatever the language:

Terminal window
export SHIELD360_URL=https://app.shield360.ai
export SHIELD360_API_KEY=<your API key> # Settings → Developer → API keys
export OTEL_SERVICE_NAME=orders-api
export SHIELD360_RASP=monitor # or block; leave unset for telemetry only
export SHIELD360_CONFIG_PUBLIC_KEY='<JWK from the app’s Runtime protection settings>'
export SHIELD360_IAST=on # optional: report vulnerabilities
export SHIELD360_GUARDS=prompt_injection:block,pii:warn # optional, Node.js: guards on LLM calls

The API key decides which project environment the app reports to. See Pin the config key for where the public key comes from.

The quickest way, with the Shield360 CLI on your machine: put shield360 run -- in front of the command you already use. Nothing is installed in the app and no file changes.

Terminal window
shield360 run -- npm start
shield360 run --app checkout --env staging -- node server.js
shield360 run -- uvicorn main:app --reload

It reads the Shield360 address and key from SHIELD360_URL and SHIELD360_API_KEY (or shield360 configure). The app is named after its package.json or pyproject.toml, else its directory (--app to choose), and its data goes to the dev environment unless --env or SHIELD360_ENVIRONMENT says otherwise. Application logs are captured. For Node, the SDK is installed once into ~/.shield360/sdk and reused. For Python, the app’s interpreter needs the shield360 package. The command’s output, exit status and Ctrl-C pass straight through.

To bake it into the app’s container image instead, shield360 init --write adds the SDK (Node) or the agent (Java) to the Dockerfile and writes the app’s settings next to it; see shield360 init.

To set it up in the app itself, or for a production start command:

Terminal window
node --require shield360/register app.js
node --import shield360/register app.mjs # ES modules
NODE_OPTIONS="--require shield360/register" npm start

The runtime protection hooks are installed before your app loads, and every http and https request is captured without middleware. ES module imports are instrumented too. Set SHIELD360_ESM_HOOK=off to leave the ES module hook out.

Each incoming request becomes a trace, named by its route when the app uses Express, Koa, Hapi or NestJS (GET /orders/:id). What the request waits on appears inside it, with nothing to install beyond shield360:

KindLibraries
Outgoing HTTPhttp, https, fetch (undici)
DatabasesPostgreSQL (pg), MySQL (mysql2, mysql), MongoDB
CachesRedis (redis, ioredis)
APIs and messagingGraphQL, gRPC, Kafka (kafkajs), the AWS SDK
AIEvery provider and framework in the integrations list

Values stay out of what is recorded: a Redis command is stored by name only (GET, not its key or value), GraphQL field values and MongoDB query values are left out, SQL is recorded without parameters (numbers and quoted strings in a mysql2 query become ?), a Kafka message key is stored as ?, and message payloads are never recorded. Health probes (Kubernetes, load balancers, uptime checks, /healthz-style paths) and the SDK’s own calls to Shield360 are not traced. Turn one off with SHIELD360_DISABLED_INSTRUMENTORS, for example SHIELD360_DISABLED_INSTRUMENTORS=graphql,kafkajs.

SHIELD360_GUARDS turns guards on for the app’s LLM calls: guard kinds (prompt_injection, pii, moderation), each with an action after a colon (allow, warn, redact, or block). The guards also send the heartbeat the Secured by Shield360 badge reads. A bundled app must keep its LLM client (@anthropic-ai/sdk, openai) outside the bundle, installed beside it.

Go, PHP and Rust have no zero-code entry point. Go and Rust compile the checks into the app, and PHP starts through its bootstrap. See each SDK’s reference.

In Go, three one-line wraps give the same request tracing after shield360.Init: shield360.Handler(mux, "orders-api") traces each request by its ServeMux route (GET /orders/{id}) and leaves health probes out, shield360.HTTPClient() (or shield360.Transport(base)) traces outgoing calls except those to Shield360, and shield360.OpenDB(driver, dsn) traces SQL statements without their arguments. Redis, MongoDB, gRPC, Kafka and AWS calls join the trace through one-line hooks in their own packages: goredis.Instrument(rdb), mongodb.Monitor(), grpctrace.DialOption() / grpctrace.ServerOption(), kafkago.WriteMessages / kafkago.StartProcess and awstrace.Instrument(&cfg) (see the Go SDK README). Keys, values, documents and message payloads are never recorded.

The Shield360 operator applies the same entry points to pods by annotation, without changing their images.