Skip to content

Commit 845d6b9

Browse files
authored
Merge branch 'GitHubSecurityLab:main' into devcontainer-configuration
2 parents 3b30d1b + 115ddda commit 845d6b9

34 files changed

+202
-72
lines changed

.github/workflows/release.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
release_tag:
7+
description: 'Release tag (e.g. v1.0.0)'
8+
required: false
9+
default: 'latest'
10+
11+
permissions:
12+
contents: read
13+
packages: write
14+
15+
jobs:
16+
release:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- name: Checkout code
20+
uses: actions/checkout@v4
21+
22+
- name: Set up Python
23+
uses: actions/setup-python@v5
24+
with:
25+
python-version: '3.11'
26+
27+
- name: Create release
28+
run: |
29+
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u GitHubSecurityLab --password-stdin
30+
python release_tools/publish_docker.py release.txt main.py ghcr.io/githubsecuritylab/seclab-taskflow-agent ${{ github.event.inputs.release_tag }}

README.md

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -115,23 +115,21 @@ MY_TASKFLOWS=~/my_taskflows MY_DATA=~/codeql_databases CODEQL_DBS_BASE_PATH=/app
115115

116116
For more advanced scenarios like e.g. making custom MCP server code available, you can alter the run script to mount your custom code into the image and configure your toolboxes to use said code accordingly.
117117

118-
Example: a custom MCP server deployment via Docker image:
119-
120118
```sh
121119
export MY_MCP_SERVERS="$PWD"/mcp_servers
122120
export MY_TOOLBOXES="$PWD"/toolboxes
123121
export MY_PERSONALITIES="$PWD"/personalities
124122
export MY_TASKFLOWS="$PWD"/taskflows
125123
export MY_PROMPTS="$PWD"/prompts
124+
export MY_DATA="$PWD"/data
126125

127126
if [ ! -f ".env" ]; then
128127
touch ".env"
129128
fi
130129

131130
docker run \
132-
--volume /var/run/docker.sock:/var/run/docker.sock \
133131
--volume "$PWD"/logs:/app/logs \
134-
--mount type=bind,src="$PWD"/env,dst=/app/.env,ro \
132+
--mount type=bind,src="$PWD"/.env,dst=/app/.env,ro \
135133
${MY_DATA:+--mount type=bind,src=$MY_DATA,dst=/app/my_data} \
136134
${MY_MCP_SERVERS:+--mount type=bind,src=$MY_MCP_SERVERS,dst=/app/my_mcp_servers,ro} \
137135
${MY_TASKFLOWS:+--mount type=bind,src=$MY_TASKFLOWS,dst=/app/taskflows/my_taskflows,ro} \
@@ -141,19 +139,6 @@ docker run \
141139
"ghcr.io/githubsecuritylab/seclab-taskflow-agent" "$@"
142140
```
143141

144-
Our default run script makes the Docker socket available to the image, which contains the Docker cli, so 3rd party Docker based stdio MCP servers also function as normal.
145-
146-
Example: a toolbox configuration using the official GitHub MCP Server via Docker:
147-
148-
```yaml
149-
server_params:
150-
kind: stdio
151-
command: docker
152-
args: ["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server"]
153-
env:
154-
GITHUB_PERSONAL_ACCESS_TOKEN: "{{ env GITHUB_PERSONAL_ACCESS_TOKEN }}"
155-
```
156-
157142
## Personalities
158143

159144
Core characteristics for a single Agent. Configured through YAML files in `personalities/`.

available_tools.py

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,49 @@
1+
import logging
2+
3+
class VersionException(Exception):
4+
pass
5+
6+
class FileTypeException(Exception):
7+
pass
8+
19
class AvailableTools:
210
"""
311
This class is used for storing dictionaries of all the available
412
personalities, taskflows, and prompts.
513
"""
6-
def __init__(self, personalities: dict, taskflows: dict, prompts: dict):
7-
self.personalities = personalities
8-
self.taskflows = taskflows
9-
self.prompts = prompts
14+
def __init__(self, yamls: dict):
15+
self.personalities = {}
16+
self.taskflows = {}
17+
self.prompts = {}
18+
self.toolboxes = {}
19+
20+
# Iterate through all the yaml files and divide them into categories.
21+
# Each file should contain a header like this:
22+
#
23+
# seclab-taskflow-agent:
24+
# type: taskflow
25+
# version: 1
26+
#
27+
for path, yaml in yamls.items():
28+
try:
29+
header = yaml['seclab-taskflow-agent']
30+
version = header['version']
31+
if version != 1:
32+
raise VersionException(str(version))
33+
filetype = header['type']
34+
if filetype == 'personality':
35+
self.personalities.update({path: yaml})
36+
elif filetype == 'taskflow':
37+
self.taskflows.update({path: yaml})
38+
elif filetype == 'prompt':
39+
self.prompts.update({path: yaml})
40+
elif filetype == 'toolbox':
41+
self.toolboxes.update({path: yaml})
42+
else:
43+
raise FileTypeException(str(filetype))
44+
except KeyError as err:
45+
logging.error(f'{path} does not contain the key {err.args[0]}')
46+
except VersionException as err:
47+
logging.error(f'{path}: seclab-taskflow-agent version {err.args[0]} is not supported')
48+
except FileTypeException as err:
49+
logging.error(f'{path}: seclab-taskflow-agent file type {err.args[0]} is not supported')

docker/run.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ if [ ! -f ".env" ]; then
55
fi
66
docker run -i \
77
--platform linux/amd64 \
8-
--volume /var/run/docker.sock:/var/run/docker.sock \
98
--volume "$PWD/"logs:/app/logs \
109
--mount type=bind,src="$PWD/".env,dst=/app/.env,ro \
1110
${MY_DATA:+--mount type=bind,src=$MY_DATA,dst=/app/my_data} \

main.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ def parse_prompt_args(available_tools: AvailableTools,
7979
l = args[0].l
8080
return p, t, l, ' '.join(args[0].prompt), help_msg
8181

82-
async def deploy_task_agents(agents: dict,
82+
async def deploy_task_agents(available_tools: AvailableTools,
83+
agents: dict,
8384
prompt: str,
8485
async_task: bool = False,
8586
toolboxes_override: list = [],
@@ -120,7 +121,7 @@ async def deploy_task_agents(agents: dict,
120121
tool_filter = create_static_tool_filter(blocked_tool_names=blocked_tools) if blocked_tools else None
121122

122123
# fetch mcp params
123-
mcp_params = mcp_client_params(YamlParser('toolboxes').get_yaml_dict(recurse=True), toolboxes)
124+
mcp_params = mcp_client_params(available_tools.toolboxes, toolboxes)
124125
for tb, (params, confirms, server_prompt, client_session_timeout) in mcp_params.items():
125126
server_prompts.append(server_prompt)
126127
# https://openai.github.io/openai-agents-python/mcp/
@@ -401,6 +402,7 @@ async def on_handoff_hook(
401402
raise ValueError("No such personality!")
402403

403404
await deploy_task_agents(
405+
available_tools,
404406
{ p:personality },
405407
prompt,
406408
run_hooks=TaskRunHooks(
@@ -575,6 +577,7 @@ async def run_prompts(async_task=False, max_concurrent_tasks=5):
575577
async def _deploy_task_agents(resolved_agents, prompt):
576578
async with semaphore:
577579
result = await deploy_task_agents(
580+
available_tools,
578581
# pass agents and prompt by assignment, they change in-loop
579582
resolved_agents,
580583
prompt,
@@ -626,9 +629,10 @@ async def _deploy_task_agents(resolved_agents, prompt):
626629

627630
if __name__ == '__main__':
628631
available_tools = AvailableTools(
629-
personalities = YamlParser('personalities').get_yaml_dict(),
630-
taskflows = YamlParser('taskflows').get_yaml_dict(),
631-
prompts = YamlParser('prompts').get_yaml_dict(dir_namespace=True))
632+
YamlParser('personalities').get_yaml_dict() |
633+
YamlParser('taskflows').get_yaml_dict() |
634+
YamlParser('prompts').get_yaml_dict(dir_namespace=True) |
635+
YamlParser('toolboxes').get_yaml_dict(recurse=True))
632636

633637
p, t, l, user_prompt, help_msg = parse_prompt_args(available_tools)
634638

mcp_servers/memcache/memcache_backend/sql_models.py

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,4 @@ class KeyValue(Base):
1313
value: Mapped[str] = mapped_column(Text)
1414

1515
def __repr__(self):
16-
return f"<KeyValue(key={self.key}, value={self.value})>"
17-
18-
class AlertResults(Base):
19-
__tablename__ = 'alert_results'
20-
21-
canonical_id: Mapped[int] = mapped_column(primary_key=True)
22-
alert_id: Mapped[str]
23-
repo: Mapped[str]
24-
rule: Mapped[str]
25-
language: Mapped[str]
26-
location: Mapped[str]
27-
result: Mapped[str] = mapped_column(Text)
28-
created: Mapped[Optional[str]]
29-
valid: Mapped[bool] = mapped_column(nullable=False, default=True)
30-
completed: Mapped[bool] = mapped_column(nullable=False, default=False)
31-
32-
relationship('AlertFlowGraph', cascade='all, delete')
33-
34-
def __repr__(self):
35-
return (f"<AlertResults(alert_id={self.alert_id}, repo={self.repo}, "
36-
f"rule={self.rule}, language={self.language}, location={self.location}, "
37-
f"result={self.result}, created_at={self.created}, valid={self.valid}, completed={self.completed})>")
38-
39-
class AlertFlowGraph(Base):
40-
__tablename__ = 'alert_flow_graph'
41-
42-
id: Mapped[int] = mapped_column(primary_key=True)
43-
alert_canonical_id = Column(Integer, ForeignKey('alert_results.canonical_id', ondelete='CASCADE'))
44-
flow_data: Mapped[str] = mapped_column(Text)
45-
repo: Mapped[str]
46-
prev: Mapped[Optional[str]]
47-
next: Mapped[Optional[str]]
48-
started: Mapped[bool] = mapped_column(nullable=False, default=False)
49-
50-
def __repr__(self):
51-
return (f"<AlertFlowGraph(alert_canonical_id={self.alert_canonical_id}, "
52-
f"flow_data={self.flow_data}, repo={self.repo}, prev={self.prev}, next={self.next}, started={self.started})>")
16+
return f"<KeyValue(key={self.key}, value={self.value})>"

misc/codeql_fetch_db.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/sh
1+
#!/bin/bash
22

33
# dep: https://github.com/cli/cli
44
# e.g. get_codeql_db.sh ntp-project/ntp cpp
@@ -9,6 +9,7 @@
99
# - csharp: The C# programming language
1010
# - go: The Go programming language
1111
# - java: The Java programming language
12+
# - javascript: The JavaScript programming language (including TypeScript)
1213
# - python: The Python programming language
1314
# - ruby: The Ruby programming language
1415
# - swift: The Swift programming language

personalities/assistant.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
seclab-taskflow-agent:
2+
type: personality
3+
version: 1
4+
15
personality: |
26
You are a helpful assistant.
37
task: |

personalities/c_auditer.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
seclab-taskflow-agent:
2+
type: personality
3+
version: 1
4+
15
personality: |
26
Your name is Ronald. You are a C programming language security expert.
37
You have the ability to call tools to aid you in your security reviews.
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
seclab-taskflow-agent:
2+
type: personality
3+
version: 1
4+
15
personality: |
2-
You are an an apples expert.
6+
You are an apples expert.
37
48
task: |
59
Answer any questions about apples.

0 commit comments

Comments
 (0)