Skip to content

Security

OrgLoop is the nervous system of your organization. Every event, every routing decision, every actor invocation flows through it. Security is architectural, not bolted on. The defaults are secure — you opt into exposure, never out of it.

Sources use outbound polling by default. OrgLoop reaches out to external systems on a schedule — nothing reaches in.

  • Zero inbound attack surface. No open ports, no public endpoints.
  • No webhook secrets to rotate or signature validation to get wrong.
  • No auth tokens exposed on your infrastructure.
  • Works behind NAT, firewalls, VPNs with zero configuration.
# Outbound polling, no inbound surface
sources:
- id: github
connector: "@orgloop/connector-github"
config:
repo: "my-org/my-repo"
poll_interval: 5m
token: "${GITHUB_TOKEN}"

Your organization reaches out. Nothing reaches in.

Events from external sources can contain adversarial content — a GitHub comment with “ignore previous instructions,” a Linear ticket with embedded authority claims. OrgLoop’s answer: transforms intercept events before they ever reach an actor.

routes:
- name: github-to-engineering
when:
source: github
events: [resource.changed]
transforms:
- ref: drop-bot-noise
- ref: dedup
then:
actor: openclaw-engineering-agent

Today, the built-in transforms handle filtering and deduplication. You can write custom script transforms that inspect payloads for injection patterns — a shell script that reads event JSON from stdin, checks for suspicious content, and exits with code 1 to drop the event. The transform pipeline is the right place for this because it runs before events reach any actor.

This is defense-in-depth: actors should still handle adversarial input, but the transport layer can filter obvious attacks before they arrive.

All configuration is validated against JSON Schema via AJV. orgloop validate enforces schemas before runtime:

$ orgloop validate
✓ connectors/github.yaml — valid source definition
✓ connectors/openclaw.yaml — valid actor definition
✗ routes/engineering.yaml — error at routes[0].transforms[1]:
Transform "my-filter" not found.
1 error, 0 warnings

At runtime, malformed events are rejected at ingestion — not when they reach an actor. Schema enforcement catches missing required fields, unexpected event types, malformed payloads, and reference integrity violations (routes pointing to nonexistent sources or actors).

Actors only see events their routes explicitly match. There is no broadcast bus, no “subscribe to everything.” Routes are allow-lists, not deny-lists.

  • The engineering agent sees GitHub and Linear events — nothing else.
  • The on-call actor sees PagerDuty alerts — not code reviews.
  • A compromised actor cannot eavesdrop on events it was never routed.

Every route is a deliberate, auditable decision about who sees what.

Connector configs support ${ENV_VAR} substitution. Secrets never live in YAML:

config:
token: "${GITHUB_TOKEN}" # GitHub
api_key: "${LINEAR_API_KEY}" # Linear
bot_token: "${SLACK_BOT_TOKEN}" # Slack

In practice:

  • Local development: .env file (git-ignored)
  • Production: platform secret stores (1Password CLI, AWS Secrets Manager, Vault)
  • CI: injected via environment

OrgLoop never logs resolved secret values. orgloop validate checks that referenced environment variables exist without printing them.

Loggers are first-class primitives in OrgLoop, not optional add-ons. Every event, every routing decision, every transform result, every delivery is logged with trace IDs:

{"ts":"...","phase":"source.emit","source":"github","event_id":"evt_abc","event_type":"resource.changed"}
{"ts":"...","phase":"transform.pass","transform":"drop-bot-noise","event_id":"evt_abc","result":"pass"}
{"ts":"...","phase":"route.match","event_id":"evt_abc","matched":"github-to-engineering"}
{"ts":"...","phase":"deliver.success","event_id":"evt_abc","target":"openclaw-engineering-agent","status":"delivered"}

You get a complete, queryable trail of what happened, why it was routed that way, and what the system did about it. Dropped events are logged with the reason. Transform mutations are logged with before/after diffs.

Terminal window
# Trace a specific event end-to-end
orgloop logs --event evt_abc123
# Show all dropped events in the last hour
orgloop logs --result drop --since 1h

See the Building Transforms guide for details on how transforms interact with the audit pipeline.

Every SOP execution is recorded with full provenance in the audit trail — a structured record of inputs, routing decisions, outputs, and content hashes. This enables post-incident forensics and real-time monitoring of agent behavior.

Each audit record captures:

  • Input: event ID, source, type, SHA-256 content hash
  • Routing: matched route, SOP file, module
  • Execution: actor, delivery status, duration
  • Outputs: side-effects with content hashes and validation flags
  • Chain tracking: depth in the event chain, parent event ID

The audit trail is queryable via the Runtime API — filter by trace ID, route, actor, or flag status.

Before SOP outputs reach external systems, OrgLoop’s output validator checks for potential payload propagation — a defense against the Viral Agent Loop (arXiv:2602.19555):

  • Instruction detection: Flags prompt injection patterns like “ignore previous instructions”, system prompt delimiters ([INST], <<SYS>>), and encoded payloads
  • Input echo detection: Flags outputs that are suspiciously similar to the input (echo/amplification attacks)
  • Scope violation detection: Flags references to URLs outside allowed domains, shell commands, and actions outside the SOP’s expected scope

Outputs with critical flags can optionally be held for human review before delivery (holdOnCritical: true in RuntimeOptions).

OrgLoop tracks event chains — when Event A triggers an SOP that produces Output B, which triggers another SOP producing Output C. This chain tracking detects runaway feedback loops:

  • Chain depth monitoring: Alerts when a trace’s event chain exceeds a configurable depth (default: 3 hops)
  • Pattern detection: Flags repeated source+type combinations within a chain
  • Circuit breaker: Automatically stops processing when chains exceed the circuit breaker depth (default: 5 hops)

Configure via RuntimeOptions:

const runtime = new Runtime({
loopDetector: {
maxChainDepth: 3, // Alert threshold
circuitBreakerDepth: 5, // Auto-stop threshold
windowMs: 300_000, // 5-minute tracking window
},
outputValidator: {
holdOnCritical: true, // Hold flagged outputs for review
allowedDomains: ['github.com', 'linear.app'],
},
});

orgloop plan shows exactly what will change before any config is applied:

$ orgloop plan
Sources:
+ github (new — poll every 5m)
~ claude-code (changed — secret added)
Transforms:
+ drop-bot-noise (new — package)
Routes:
+ github-to-engineering (new)
Plan: 3 to add, 1 to change, 0 to remove.
Run `orgloop start` to execute this plan.

No surprise mutations. You review the diff, then start. Infrastructure-as-code discipline applied to your organization’s operational topology.

Connectors are npm packages — auditable source code, not opaque marketplace plugins.

  • @orgloop/* — first-party connectors, maintained by the OrgLoop team
  • Community connectors — published on npm, standard review applies
  • npm audit for vulnerability scanning
  • package-lock.json for deterministic installs
  • Full source code inspection before you trust a connector with your event stream

No walled-garden marketplace, no binary blobs.

OrgLoop’s default network posture is zero inbound connections:

  • Sources poll outbound — no listening ports
  • orgloop start runs as a local daemon with the HTTP server bound to 127.0.0.1 (localhost only)
  • The built-in REST API, control API, and webhook endpoints are not exposed to the network by default

For production deployments:

  • Run behind Tailscale, WireGuard, or your VPN of choice
  • The HTTP server binds to localhost by default; exposing it externally requires a conscious decision via ORGLOOP_HOST
  • Webhook ingestion (for push-based sources like coding-agent hooks) binds to localhost by default