access-control — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited access-control (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Tool availability: some MCP tools named here live in thefulltoolset profile — if one is not advertised on this connection, tell the user to reconnect the MCP server with?toolsets=full(or use thecplnCLI fallback). Reads and deletes work on every profile via the genericlist_resources/get_resource/delete_resourcetools.
A policy targets one resource kind and binds permissions to principals (users, groups, service accounts, workload identities). The common failure is a policy that exists but grants nothing — a wrong targetKind, permission name, or principal link fails with no error — so read the policy back after writing.
| Layer | Scope | Controls |
|---|---|---|
| Billing-account roles | account-wide (set on the billing account, separate from org policies) | billing_admin, billing_viewer, org_creator — none grant org-resource access |
| Org policies | per resource kind | all day-to-day access |
A caller is allowed an action when some policy on the resource's kind has a binding that lists that action (or a permission implying it) and names the caller — or a group the caller is in.
A policy = one `targetKind` + a target scope + bindings.
kind: policy
name: app-secret-access
targetKind: secret # exactly one resource kind
targetLinks: # OR `target: all` OR `targetQuery:` (pick one)
- //secret/database-url
bindings: # ≤ 50
- permissions: [reveal, use]
principalLinks: # 1–200
- //gvc/production/identity/app-identityLimits: bindings ≤ 50; principalLinks 1–200 per binding; targetLinks ≤ 200. origin is read-only — default (yours) or builtin (locked; see Built-ins).
Target scope (pick one): target: all (org-wide roles) · targetLinks (specific resources) · targetQuery (tag query — see query-spec).
Valid target kinds: the targetKind enum accepts all 33 resource kinds, but only the 20 kinds with permission schemas (the ones get_permissions accepts) are meaningful targets: workload, secret, gvc, identity, image, org, policy, group, serviceaccount, user, volumeset, domain, location, ipset, mk8s, cloudaccount, agent, auditctx, quota, task.
Create vs update:
create_policy builds one binding from addPermissions × (addUsers/addGroups/addServiceAccounts/addIdentities) — providing only one side is an error (a binding needs both). It also requires exactly one target scope (targetAll / targetLinks / targetQuery). For several distinct bindings, use update_policy addBindings.update_policy merges bindings (matched by exact permission set — you can't extend a set) but replaces targets (targetLinks wholesale, removeTargetLinks incremental, targetAll — mutually exclusive).`get_permissions` (`kind`) is the source of truth — it returns the kind's exact permission list and its implication map. Confirm names with it before writing a policy; never hand-write them, and don't assume a kind only has create / delete / edit / view / manage.
Two traps that don't need a lookup:
Many kinds add non-obvious permissions beyond CRUD — e.g. secret reveal/use, image pull, workload connect/exec.*, serviceaccount addKey, user invite/impersonate, mk8s clusterAdmin — so pull the real set with get_permissions.
| Type | Link |
|---|---|
| User | //user/EMAIL |
| Group (preferred) | //group/NAME |
| Service account | //serviceaccount/NAME |
| Workload identity | //gvc/GVC/identity/NAME (GVC-scoped — never //identity/NAME) |
An identity never belongs to a group, so authorize it only with a binding that names its exact link. At runtime the attached identity is the workload's API credential: calls from inside the workload with the injected CPLN_TOKEN against CPLN_ENDPOINT carry exactly the permissions policies grant that identity — nothing more.
Members are users and service accounts only (≤ 200). Bind policies to groups, not individuals.
create_group (name, memberLinks, memberQuery, identityMatcher); edit_group (addMemberLinks / removeMemberLinks — read first with get_resource (kind="group")).memberQuery matches users by tag query; identityMatcher matches identities by a jmespath/javascript expression.add_key_to_service_account (serviceAccountName, `keyDescription` required, optional groupName) — auto-creates the SA if missing and returns the key once (save it; lost = revoke + remint). create_service_account makes one with no key.update_service_account removeKeys: [NAME] (immediate). delete_resource (kind="service_account") revokes all keys.CPLN_TOKEN secret/env var — the CLI uses it ahead of any profile (and works without one); don't pass --token on the command line (it leaks into logs). Full setup: gitops-cicd.invite_user_to_org (email, optional groupName).get_resource (kind="user") / delete_resource (kind="user") take `identifier` (id or email); list_resources (kind="user") has an email filter. No create_user/update_user.| Resource | Name | Grants |
|---|---|---|
| Group | superusers | manage on every kind (creator auto-added) |
| Group | viewers | view on every kind |
| Service account | controlplane | platform-internal — off-limits |
| Policies | superusers-KIND / viewers-KIND | origin: builtin, target: all |
viewers for read-only) — don't recreate admin policies.superusers).create_policy builds these; the cpln apply -f manifest is the policy-as-code equivalent for CI/CD.
superusers. Scoped admin — one policy per targetKind with [manage].workload [connect, create, delete, edit, exec, view] + secret [create, delete, edit, reveal, use, view] on a developers group.viewers.workload [create, delete, edit, view] + image [create, pull, view] + secret [use, view] on //serviceaccount/cicd-deployer.spec.identityLink).policy [view] + auditctx [view] on an auditors group.get_cpln_rules (once per mutating session) and read this skill.get_permissions for the kind — confirm permission names.list_resources (kind="policy") / get_resource (kind="policy") (+ get_resource kind="group" / kind="service_account").create_policy / update_policy (+ group / SA / user tools).| Tool | Purpose | Key params |
|---|---|---|
mcp__cpln__get_permissions | Permissions + implications for a kind | kind |
mcp__cpln__list_resources (kind="policy") / get_resource (kind="policy") | List / read policies | name |
mcp__cpln__create_policy | Create a policy | name, targetKind, targetAll/targetLinks/targetQuery, addPermissions, addUsers/addGroups/addServiceAccounts/addIdentities |
mcp__cpln__update_policy | Update metadata, targets, bindings | name, addBindings/removeBindings, targetLinks/removeTargetLinks/targetAll, targetQuery |
mcp__cpln__delete_resource (kind="policy") | Delete a policy (destructive) | name |
mcp__cpln__list_resources (kind="group") / get_resource (kind="group") | List / read groups | name |
mcp__cpln__create_group | Create a group | name, memberLinks, memberQuery, identityMatcher |
mcp__cpln__edit_group | Add/remove members, update meta | name, addMemberLinks, removeMemberLinks |
mcp__cpln__delete_resource (kind="group") | Delete a group (destructive) | name |
mcp__cpln__list_resources (kind="service_account") / get_resource (kind="service_account") | List / read SAs (key metadata only) | name |
mcp__cpln__create_service_account | Create an SA (no key) | name, description |
mcp__cpln__add_key_to_service_account | Mint a key (auto-creates SA) | serviceAccountName, keyDescription, groupName |
mcp__cpln__update_service_account | Update meta / revoke keys | name, removeKeys |
mcp__cpln__delete_resource (kind="service_account") | Delete an SA (revokes all keys) | name |
mcp__cpln__list_resources (kind="user") / get_resource (kind="user") | List / read users | email / identifier |
mcp__cpln__invite_user_to_org | Invite a user by email | email, groupName |
mcp__cpln__delete_resource (kind="user") | Remove a user (destructive) | identifier |
CLI fallback (read the cpln skill first; verify with cpln <resource> --help): policy-as-code in CI/CD (CPLN_TOKEN + cpln apply -f), cpln RESOURCE permissions to list a kind's permissions, cpln policy access-report NAME to audit a policy.
| Need | Skill |
|---|---|
Query language for targetQuery / memberQuery | query-spec |
| Org creation, billing, profiles, SSO | org-management |
| Audit trail of policy / access changes | audit-compliance |
| Full workload secret-access flow | setup-secret |
| Credential-free cloud access (AWS / GCP / Azure / NGS) | setup-cloud-access |
| Workload identities, private-network connectivity | native-networking |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.