| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- {
- "name": "verify-system-collections-refused",
- "comment": "A workflow gets nowhere near the collections SmartBotic runs on, even with defaultAccess read-write. This is the setting that matters: a blanket yes to every unlisted name. Reading projects exposes who may do what; writing it is a grant of access somebody gave themselves. Writing workflows edits another workflow's graph without passing a single permission check.\n\nThis was open. The runner and the webserver each kept their own list of protected collections and the two had drifted - the runner named five, the webserver ten, and \"projects\" was in neither. The list is one list now, in storage/system_collections.hpp, so a name added there is protected in both places at once.\n\nThe control is an ordinary collection written under the same defaultAccess, which must still succeed: this test is about protecting the system's own data, not about turning defaultAccess off.",
- "settings": {
- "storagePermissions": {
- "defaultAccess": "read-write"
- }
- },
- "nodes": [
- {
- "id": "n1",
- "name": "Trigger",
- "type": "click-trigger",
- "position": { "x": 0, "y": 0 },
- "config": {}
- },
- {
- "id": "projects",
- "name": "Read who may do what",
- "type": "storage-query",
- "position": { "x": 0, "y": 100 },
- "config": { "collectionSource": "manual", "collectionManual": "projects" }
- },
- {
- "id": "workflows",
- "name": "Read every workflow",
- "type": "storage-query",
- "position": { "x": 0, "y": 200 },
- "config": { "collectionSource": "manual", "collectionManual": "workflows" }
- },
- {
- "id": "users",
- "name": "Read the password hashes",
- "type": "storage-query",
- "position": { "x": 0, "y": 300 },
- "config": { "collectionSource": "manual", "collectionManual": "users" }
- },
- {
- "id": "escalate",
- "name": "Grant itself a project role",
- "type": "storage-insert",
- "position": { "x": 0, "y": 400 },
- "config": {
- "collectionSource": "manual",
- "collectionManual": "projects",
- "documentData": "{\"name\": \"trespass\"}"
- }
- },
- {
- "id": "control",
- "name": "An ordinary collection still works",
- "type": "storage-insert",
- "position": { "x": 0, "y": 500 },
- "config": {
- "collectionSource": "manual",
- "collectionManual": "wfprobe_control_collection",
- "documentData": "{\"probe\": \"control\"}"
- }
- }
- ],
- "connections": [
- { "sourceNodeId": "n1", "sourceOutput": "main", "targetNodeId": "projects", "targetInput": "data" },
- { "sourceNodeId": "projects", "sourceOutput": "main", "targetNodeId": "workflows", "targetInput": "data" },
- { "sourceNodeId": "workflows", "sourceOutput": "main", "targetNodeId": "users", "targetInput": "data" },
- { "sourceNodeId": "users", "sourceOutput": "main", "targetNodeId": "escalate", "targetInput": "data" },
- { "sourceNodeId": "escalate", "sourceOutput": "main", "targetNodeId": "control", "targetInput": "data" }
- ],
- "expect": {
- "projects": {
- "status": "completed",
- "output": { "error": "No read access to collection: projects" }
- },
- "workflows": {
- "status": "completed",
- "output": { "error": "No read access to collection: workflows" }
- },
- "users": {
- "status": "completed",
- "output": { "error": "No read access to collection: users" }
- },
- "escalate": {
- "status": "completed",
- "output": { "success": false, "error": "No write access to collection: projects" }
- },
- "control": {
- "status": "completed",
- "output": { "success": true }
- }
- }
- }
|