Skip to content

Commit 42807f1

Browse files
committed
Release v4.5.121
1 parent 0d40fa9 commit 42807f1

File tree

17 files changed

+130
-12
lines changed

17 files changed

+130
-12
lines changed

.github/workflows/claude.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,36 @@ jobs:
147147
private-key: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
148148
owner: ${{ github.repository_owner }}
149149

150+
- name: Check for Fork PR
151+
id: check_fork
152+
uses: actions/github-script@v7
153+
with:
154+
script: |
155+
if (context.issue.pull_request) {
156+
const pr = await github.rest.pulls.get({
157+
owner: context.repo.owner,
158+
repo: context.repo.repo,
159+
pull_number: context.issue.number
160+
});
161+
if (pr.data.head.repo && pr.data.head.repo.full_name !== context.repo.full_name) {
162+
core.setOutput('is_fork', 'true');
163+
core.setOutput('clone_url', pr.data.head.repo.clone_url);
164+
return;
165+
}
166+
}
167+
core.setOutput('is_fork', 'false');
168+
150169
- name: Checkout repository
151170
uses: actions/checkout@v4
152171
with:
153172
fetch-depth: 0
154173
token: ${{ steps.app-token.outputs.token }}
155174

175+
- name: Setup Remote for Fork PR
176+
if: steps.check_fork.outputs.is_fork == 'true'
177+
run: |
178+
git remote set-url origin ${{ steps.check_fork.outputs.clone_url }}
179+
156180
- uses: anthropics/claude-code-action@beta
157181
env:
158182
GH_TOKEN: ${{ steps.app-token.outputs.token }}
@@ -164,6 +188,7 @@ jobs:
164188
label_trigger: "claude"
165189

166190
direct_prompt: |
191+
${{ steps.check_fork.outputs.is_fork == 'true' && 'CRITICAL: THIS IS A PULL REQUEST FROM A FORK. YOU DO NOT HAVE PUSH PERMISSIONS TO THIS REPOSITORY. ONLY READ FILES, VALIDATE CODE, AND PROVIDE YOUR COMMENTS/FEEDBACK DIRECTLY IN THIS PR VIA COMMENTS. DO NOT ATTEMPT TO PUSH OR CREATE PULL REQUESTS.\n\n' || '' }}
167192
You are working on the PraisonAI SDK. Follow AGENTS.md strictly.
168193
169194
STEP 0 — SETUP GIT IDENTITY & AUTH (GLOBAL — required for all repos):

docker/Dockerfile.chat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
1616
# Install Python packages (using latest versions)
1717
RUN pip install --no-cache-dir \
1818
praisonai_tools \
19-
"praisonai>=4.5.120" \
19+
"praisonai>=4.5.121" \
2020
"praisonai[chat]" \
2121
"embedchain[github,youtube]"
2222

docker/Dockerfile.dev

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ RUN mkdir -p /root/.praison
2020
# Install Python packages (using latest versions)
2121
RUN pip install --no-cache-dir \
2222
praisonai_tools \
23-
"praisonai>=4.5.120" \
23+
"praisonai>=4.5.121" \
2424
"praisonai[ui]" \
2525
"praisonai[chat]" \
2626
"praisonai[realtime]" \

docker/Dockerfile.ui

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
1616
# Install Python packages (using latest versions)
1717
RUN pip install --no-cache-dir \
1818
praisonai_tools \
19-
"praisonai>=4.5.120" \
19+
"praisonai>=4.5.121" \
2020
"praisonai[ui]" \
2121
"praisonai[crewai]"
2222

src/praisonai-agents/praisonaiagents/tools/python_tools.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ def _validate_code_ast(code: str):
6161
'ag_frame', 'ag_code', 'tb_frame', 'tb_next',
6262
'f_globals', 'f_locals', 'f_builtins', 'f_code',
6363
'co_consts', 'co_names',
64+
'__getattribute__', '__getattr__', '__setattr__', '__delattr__',
65+
'__dir__', '__get__', '__set__', '__delete__',
6466
})
6567

6668
for node in ast.walk(tree):
@@ -84,6 +86,15 @@ def _validate_code_ast(code: str):
8486
'setattr', 'delattr', 'dir',
8587
):
8688
return f"Call to '{func.id}' is not allowed"
89+
90+
# Block dangerous constants (strings containing dunders)
91+
# Fallback for Python 3.7 ast.Str
92+
if isinstance(node, ast.Constant) and isinstance(node.value, str):
93+
if any(attr in node.value for attr in _blocked_attrs):
94+
return f"String constant contains restricted attribute name"
95+
elif type(node).__name__ == 'Str':
96+
if any(attr in getattr(node, 's', '') for attr in _blocked_attrs):
97+
return f"String constant contains restricted attribute name"
8798

8899
return None
89100

@@ -152,6 +163,8 @@ def safe_execute():
152163
'ag_frame', 'ag_code', 'tb_frame', 'tb_next',
153164
'f_globals', 'f_locals', 'f_builtins', 'f_code',
154165
'co_consts', 'co_names',
166+
'__getattribute__', '__getattr__', '__setattr__', '__delattr__',
167+
'__dir__', '__get__', '__set__', '__delete__',
155168
}}
156169
157170
for node in ast.walk(tree):
@@ -179,6 +192,22 @@ def safe_execute():
179192
"stderr": f"Call to '{{node.func.id}}' is not allowed",
180193
"success": False
181194
}}
195+
if isinstance(node, ast.Constant) and isinstance(node.value, str):
196+
if any(attr in node.value for attr in blocked_attrs):
197+
return {{
198+
"result": None,
199+
"stdout": "",
200+
"stderr": "String constant contains restricted attribute name",
201+
"success": False
202+
}}
203+
elif type(node).__name__ == 'Str':
204+
if any(attr in getattr(node, 's', '') for attr in blocked_attrs):
205+
return {{
206+
"result": None,
207+
"stdout": "",
208+
"stderr": "String constant contains restricted attribute name",
209+
"success": False
210+
}}
182211
183212
# Create safe globals
184213
# Create a safe getattr that blocks dunder access (defense-in-depth)

src/praisonai-agents/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "praisonaiagents"
7-
version = "1.5.120"
7+
version = "1.5.121"
88
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
99
readme = "README.md"
1010
requires-python = ">=3.10"

src/praisonai-agents/uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/praisonai/praisonai.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ class Praisonai < Formula
33

44
desc "AI tools for various AI applications"
55
homepage "https://github.com/MervinPraison/PraisonAI"
6-
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v4.5.120.tar.gz"
7-
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v4.5.120.tar.gz | shasum -a 256`.split.first
6+
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v4.5.121.tar.gz"
7+
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v4.5.121.tar.gz | shasum -a 256`.split.first
88
license "MIT"
99

1010
depends_on "python@3.11"

src/praisonai/praisonai/cli/features/action_orchestrator.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,17 @@ async def _apply_step(self, step: ActionStep) -> Optional[Dict[str, Any]]:
444444

445445
elif step.action_type == ActionType.SHELL_COMMAND:
446446
import subprocess
447+
448+
# Block shell injection characters
449+
banned_chars = [';', '&', '|', '$', '`']
450+
if any(char in step.target for char in banned_chars):
451+
return {
452+
"command": step.target,
453+
"stdout": "",
454+
"stderr": "Command contains blocked shell characters",
455+
"returncode": -1
456+
}
457+
447458
result = subprocess.run(
448459
step.target,
449460
shell=True,

src/praisonai/praisonai/cli/features/job_workflow.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,11 @@ def _execute_step(self, step_type: str, target: Any, step: Dict, flags: Dict) ->
233233

234234
def _exec_shell(self, cmd: str, step: Dict) -> Dict:
235235
"""Execute a shell command."""
236+
# Block dangerous shell injection characters
237+
banned_chars = [';', '&', '|', '$', '`']
238+
if any(char in cmd for char in banned_chars):
239+
return {"ok": False, "error": "Command contains blocked shell characters"}
240+
236241
cwd = step.get("cwd", self._cwd)
237242
env = self._build_env(step)
238243
result = subprocess.run(

0 commit comments

Comments
 (0)