Skip to content

Security

Builds run in your AWS account, so the question a security team asks is what SquidCI gets there. In short: no standing access. There is no cross-account role, nothing SquidCI can assume, and no credential of ours in your account. One thing is opened to SquidCI, and it can send instructions, not read anything.

You create the stack yourself from the aws page, and can read its template first: the or create the stack yourself section links it. It creates, in the account and region you chose:

  • Roles for its own parts, each trusted only to the AWS service that runs it: the worker instances, the CloudFormation service that builds worker groups (with a ceiling on what those stacks may create), and the functions that apply worker groups, report on them, answer SquidCI’s challenges and update the plane’s code.
  • A task role, squidci-<slug>-task, which each job runs as — created with no permissions; it gains the right to assume your target accounts’ ci roles as you add them.
  • A KMS signing key the plane proves its identity with. Its key policy names your account only: SquidCI cannot use, disable or delete it, and the private half never leaves KMS.
  • An EventBridge bus, squidci-<slug>, which SquidCI sends to.
  • Worker groups, later, as child stacks, within the ceiling above.

The code it runs is published signed, and every function enforces the signature: an unsigned or altered zip is refused, by the plane’s updater and by AWS alike.

Principal: arn:aws:iam::<SquidCI's account>:root
Action: events:PutEvents
Resource: the squidci-<slug> event bus

One action, on one bus, from one account: how SquidCI sends the daily heartbeat challenge and worker group instructions. Nothing can be read through it. A worker group change it asks for is applied by your own function, within the ceiling your stack set.

  • To SquidCI: worker and job status, heartbeats, and job logs — what your steps print. SquidCI keeps logs for 30 days and serves them only through short-lived signed links. Build output often contains things nobody meant to print, so treat it as you would any log store: don’t echo secrets.
  • Values a job exports for other jobs: short strings, shown with the job.
  • From SquidCI: templates, the plane’s code and the worker agent, from a public read-only bucket, and SquidCI’s runner image from ECR Public. Your account reaches out for these; nothing is pushed in.

Your workers call two SquidCI hosts over HTTPS: the API of your organization’s region and auth.squidci.cloud, to exchange a signed assertion for a token. They need outbound internet; they accept no inbound connections.

  • Your source code. The GitHub App mints short-lived tokens that your workers clone with, in your account. SquidCI reads only what GitHub tells it about changes, and your pipeline file.
  • Your secrets and build output, beyond what is printed to the log.
  • Anything in your AWS account: there is no permission to read it.
  • Each job runs in its own container under Sysbox, unprivileged, so it can run Docker without being given the host. Jobs cannot reach the instance’s own credentials: the metadata service refuses them a token.
  • A job’s AWS credentials are the task role’s, held by a session policy to exactly the target accounts its pipeline file names. See AWS access for jobs.
  • Pull requests get no AWS access at all, and run only checks, tests and builds: until merged, the pipeline file is its author’s. Pull requests from forks are not built.

disconnect on the aws page makes SquidCI forget the account and stop sending it work at once. It removes nothing from AWS: delete the SquidCI stack in CloudFormation, which removes its worker groups, roles and key.