Back to skill

Security audit

Contract Risk Analyzer

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but it handles sensitive contracts with under-disclosed external AI calls, configurable destinations, subscription-token verification, and residual files in /tmp.

Review this skill before installing if contracts may contain personal data, signatures, bank details, trade secrets, or confidential terms. Use only a trusted HTTPS AI endpoint, prefer a dedicated low-privilege API key, avoid passing subscription tokens on the command line, and delete /tmp/contracts artifacts after reports are delivered. Do not use it for highly sensitive contracts unless the provider, retention, and compliance terms are acceptable.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/analyze_contract.py:266
Finding

Sensitive Contract Data Can Be Sent to an Arbitrary API Endpoint

Content
View full analysis

Vulnerability Details

File Location: scripts/analyze_contract.py:203-215, 266-285; README.md:26-27
Vulnerability Type: Unrestricted transmission of confidential data to a configurable endpoint
Risk Level: High

Vulnerable Code

python
def build_analysis_prompt(text: str, contract_type: str, language: str, tier: str = "FREE") -> str:
    """Build the AI prompt for contract risk analysis."""

    truncated = text[-8000:] if len(text) > 8000 else text

    # Key terms table is only for STD and above
    key_terms_instruction = ""
    if tier in ("STD", "PRO", "MAX"):
        key_terms_instruction = '''
    "key_terms": {
      "parties": ["Party A", "Party B", ...],
      "contract_value": "amount if stated, otherwise 'Not specified'",
      "payment_terms": "payment conditions summary",
      "duration": "contract duration/term",
      "termination": "termination conditions",
      "breach_penalties": "breach of contract penalties",
      "dispute_resolution": "dispute resolution clause",
      "governing_law": "applicable law/jurisdiction"
    },
'''

The extracted text is subsequently inserted into the prompt:

python
## Contract Text:
{truncated}

The prompt is sent to an environment-configurable endpoint:

python
def call_ai_analysis(prompt: str, model: str = "minimax/MiniMax-M2") -> dict:
    """Call AI via OpenAI-compatible API."""
    import os

    api_key = os.environ.get("OPENAI_API_KEY", "")
    base_url = os.environ.get("OPENAI_API_BASE", "https://api.minimax.chat/v1")

    if not api_key:
        # Fallback: try direct OpenAI
        api_key = os.environ.get("OPENAI_API_KEY_FALLBACK", "")
        base_url = os.environ.get("OPENAI_API_BASE_FALLBACK", "https://api.openai.com/v1")

    if not api_key:
        return {"error": "No API key configured. Set OPENAI_API_KEY or OPENAI_API_KEY_FALLBACK environment variable."}

    try:

...[truncated 2577 chars]
Remediation
View remediation

Remediation Suggestions

  1. Permit only an explicit allowlist of reviewed HTTPS API hosts by default.
  2. Parse and validate the destination URL before creating the client.
  3. Reject plaintext HTTP, embedded credentials, redirects to unapproved hosts, loopback addresses, link-local addresses, and private-network destinations.
  4. Require an explicit advanced opt-in before allowing custom endpoints.
  5. Before transmission, tell the user which host will receive the document and what data will be sent.
  6. Obtain informed consent before sending contract text to a third party.
  7. Add configurable redaction for personal identifiers, financial information, signatures, and other sensitive fields.
  8. Document the selected provider's retention, training, and privacy policies.
  9. Use a narrowly scoped API credential dedicated to this Skill.
  10. Avoid following cross-origin redirects that could forward authorization headers or contract content to another host.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/analyze_contract.py:434
Finding

Subscription Bearer Token Is Accepted Through the Process Command Line and Sent to a Third Party

Content
View full analysis

Vulnerability Details

File Location: scripts/analyze_contract.py:18, 39-57, 434-447
Vulnerability Type: Insecure secret handling and external credential disclosure
Risk Level: Medium

Vulnerable Code

python
VERIFY_URL = "https://api.yk-global.com/v1/verify"
python
def verify_token(api_key: str) -> dict:
    """
    Verify API key via 91Skillhub API.
    Returns dict with keys: valid (bool), tier (str), error (str, if failed).
    On network error, degrades to FREE tier gracefully.
    """
    if not api_key:
        return {"valid": False, "tier": "FREE", "error": "No API key provided"}

    try:
        req = urllib.request.Request(
            VERIFY_URL,
            method="POST",
            headers={
                "Authorization": f"Bearer {api_key}",
                "Content-Type": "application/json",
            },
        )
        with urllib.request.urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read().decode("utf-8"))

The secret is accepted as a command-line argument:

python
parser.add_argument("--api-key", default="",
                    help="91Skillhub API key for automatic tier verification")

It is then passed to the verification function:

python
# Verify token if api_key provided; degrade to FREE on failure
if args.api_key:
    verify_result = verify_token(args.api_key)
    if verify_result["valid"]:
        tier = verify_result["tier"]
    else:
        tier = "FREE"

Technical Analysis

Command-line arguments are not an appropriate channel for long-lived secrets. Depending on the operating system and deployment environment, arguments may be visible through process inspection, shell history, job runners, audit logs, crash reports, or observability platforms.

The complete reusable token is also transmitted as an HTTP bearer credential to api.yk-global.com. Although HTTPS ...[truncated 1278 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the --api-key command-line option for production use.
  2. Read the token from a protected environment variable, operating-system keyring, secret manager, or non-echoing stdin prompt.
  3. Ensure examples and orchestration code never place secrets in shell command strings.
  4. Use short-lived, narrowly scoped verification credentials.
  5. Prefer a signed challenge-response protocol or a non-reversible token identifier instead of transmitting a reusable bearer token.
  6. Clearly disclose the verification destination and purpose.
  7. Prevent the authorization value from appearing in application logs, exception reports, or debug traces.
  8. Rotate existing credentials if they have already been used through command-line arguments in logged environments.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/analyze_contract.py:461
Finding

Contract-Derived Reports Are Retained in a Shared Temporary Location Without Secure Cleanup

Content
View full analysis

Vulnerability Details

File Location: scripts/analyze_contract.py:461-464, 490-500; SKILL.md:178-180, 240-242
Vulnerability Type: Insecure temporary-file storage and retention
Risk Level: Medium

Vulnerable Code

python
# Ensure temp dir exists
os.makedirs("/tmp/contracts", exist_ok=True)

# Determine output path
if args.output:
    report_path = args.output
else:
    file_uuid = str(uuid.uuid4())[:8]
    report_path = f"/tmp/contracts/{file_uuid}_report.md"

The report is written without an explicit restrictive file mode and is not deleted:

python
# Save report
os.makedirs(os.path.dirname(report_path), exist_ok=True)
with open(report_path, "w", encoding="utf-8") as f:
    f.write(report_md)
print(f"[INFO] Report saved to: {report_path}", file=sys.stderr)

# Step 5: Export CSV if requested (STD+)
csv_path = None
if args.export_csv and tier in ("STD", "PRO", "MAX"):
    csv_path = export_csv(report_path, analysis, contract_type, language)
    print(f"[INFO] CSV exported to: {csv_path}", file=sys.stderr)

This conflicts with the stated retention guidance:

markdown
- All uploaded PDFs stored in `/tmp/contracts/` (auto-cleanup optional)
- Reports saved in same directory with `_report.md` suffix
- Do NOT store contract text long-term; clean up after report is delivered

Technical Analysis

Generated reports can contain contract summaries, party identities, payment conditions, values, termination clauses, liabilities, and other sensitive contract-derived information. The implementation stores those reports and optional CSV files under /tmp/contracts by default.

It does not create the directory with an explicit 0700 permission mode, create report files with an explicit 0600 mode, apply a retention period, or delete artifacts after delivery. No finally cleanup path is present. Actual exposure depends on the process umask, pre-existing directo ...[truncated 1202 chars]

Remediation
View remediation

Remediation Suggestions

  1. Create a per-run private temporary directory with tempfile.TemporaryDirectory.
  2. Set directory permissions to 0700 and artifact permissions to 0600.
  3. Retain the full random UUID or use securely generated temporary filenames.
  4. Delete input PDFs, reports, OCR intermediates, and CSV exports immediately after successful delivery unless the user explicitly requests retention.
  5. Put cleanup logic in a finally block so it executes after errors.
  6. If retention is required, define and enforce a short expiration period.
  7. Validate that user-supplied output paths point to authorized locations.
  8. Document residual-data behavior and provide users with a deletion option.

T08 · Insecure Dependencies

Warning
Location
scripts/requirements.txt:1
Finding

Dependencies Are Installed Without Exact Version or Integrity Pinning

Content
View full analysis

Vulnerability Details

File Location: scripts/requirements.txt:1-8; README.md:10-13
Vulnerability Type: Uncontrolled dependency resolution and non-reproducible installation
Risk Level: Medium

Vulnerable Code

text
# Contract Risk Reviewer - Python Dependencies
# Install with: pip install -r requirements.txt

PyMuPDF>=1.23.0
pdfplumber>=0.10.0
pytesseract>=0.3.10
pdf2image>=1.16.0
openai>=1.0.0

The documented installation command resolves packages from the active pip index:

bash
pip install -r scripts/requirements.txt

Technical Analysis

Every dependency uses an open-ended minimum version. Consequently, installations performed at different times can resolve to different package versions, including releases that have not been reviewed with this Skill.

Python package installation may execute build-system code, and imported dependencies execute with the same privileges as the Skill. No lock file, package hashes, upper bounds, or trusted index configuration is supplied. This creates avoidable supply-chain and reproducibility exposure.

The audit did not identify a currently malicious or typosquatted dependency in the listed package names. The finding concerns the unsafe resolution policy rather than proof that a listed package is presently compromised.

Attack Path

  1. A future dependency release is compromised, becomes malicious, or introduces a security regression.
  2. Alternatively, the user's configured pip index is compromised or serves an unauthorized package build.
  3. The user follows the documented pip install -r scripts/requirements.txt command.
  4. Pip selects the uncontrolled newer version because it satisfies the >= constraint.
  5. Malicious build or import-time code executes with the privileges of the installing user or Skill runtime.

Impact Assessment

A compromised dependency could obtain the same filesystem, environment-variable, and networ ...[truncated 362 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin every direct and transitive dependency to an exact reviewed version.
  2. Generate a lock file through a controlled dependency-resolution process.
  3. Record cryptographic hashes and install with pip's --require-hashes option.
  4. Configure and document a trusted package index.
  5. Install in an isolated virtual environment under a non-privileged account.
  6. Use automated vulnerability and provenance scanning for dependency updates.
  7. Review and deliberately update locked versions on a defined maintenance schedule.
  8. Avoid recommending privileged pip installation.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
Findings (25)

Tainted flow: 'req' from os.environ.get (line 49, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/analyze_contract.py (reported line 57)May include surrounding context.

python
"Content-Type": "application/json",
            },
        )
        with urllib.request.urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read().decode("utf-8"))
            if data.get("success") and data.get("valid"):
                tier = _map_prefix_to_tier(api_key)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The README instructs users to configure an external OpenAI-compatible endpoint and implies contract analysis is performed through that API, but it does not warn users that contract contents may be transmitted to a third-party service. Because contracts often contain confidential business or personal data, undisclosed external transmission creates a significant privacy and compliance risk.

Content

No source excerpt is available for this finding.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/analyze_contract.py (reported line 259)May include surrounding context.

python
- If no risks found, return empty risk_report array []
- Respond ONLY with valid JSON — no markdown code blocks, no explanation outside the JSON
"""
    return prompt


def call_ai_analysis(prompt: str, model: str = "minimax/MiniMax-M2") -> dict:

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · README.md (reported line 17)May include surrounding context.

md
# For OCR support (recommended for scanned contracts):
# Ubuntu/Debian:
sudo apt-get install tesseract-ocr tesseract-ocr-chi-sim

# macOS:
brew install tesseract tesseract-lang

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILLHUB.md (reported line 74)May include surrounding context.

md
# For OCR support (recommended for scanned contracts):
# Ubuntu/Debian:
sudo apt-get install tesseract-ocr tesseract-ocr-chi-sim

# macOS:
brew install tesseract tesseract-lang

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The README references an external API endpoint for AI analysis, which means contract contents may leave the local environment. In the context of legal document review, external transmission materially raises confidentiality, jurisdiction, and regulatory exposure, especially if users are not informed or the endpoint is custom and untrusted.

Content

Scanner excerpt · README.md (reported line 27)May include surrounding context.

bash
export OPENAI_API_KEY="your-api-key"
export OPENAI_API_BASE="https://api.minimax.chat/v1"  # or your custom endpoint

3. 运行分析

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documented trigger is simply '合同审查' (contract review), which is broad enough to overlap with ordinary user requests about contracts. In an agent platform, overly generic invocation phrases can cause accidental activation and unintended processing of sensitive documents or text without the user clearly intending to invoke this specific skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The workflow explicitly states that PDFs are saved to /tmp/contracts/.pdf during processing, but the skill description does not warn users about temporary local storage. Sensitive contracts written to disk can be exposed to other local processes, backups, or delayed cleanup if the environment is shared or misconfigured.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The example output explicitly fixes the report language as Chinese ("语言: 中文"), and the README is written as though the skill operates in Chinese, but it does not state this as an opt-in regional constraint or offer a language choice. That can violate language/locale policy if users are implicitly forced into one language.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill instructs downloading user-supplied contracts, extracting their contents, and sending contract text to an external AI model, but it does not present a clear upfront privacy notice, consent step, or data-handling boundary before transmission. Contracts commonly contain highly sensitive commercial, personal, and legal information, so silent exfiltration to third-party processing can create confidentiality, compliance, and contractual exposure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

该技能主打上传合同 PDF 并进行 AI 分析,但描述中缺少对合同可能包含个人信息、商业秘密、签章、付款信息等敏感数据的明确警示,也未说明数据会被传输到 OCR 或 OpenAI 兼容接口。对于合同审查这一高敏感场景,缺失透明告知会显著增加隐私泄露、合规违规和用户误用风险。

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

技能触发条件写成“发送‘合同审查’或上传 PDF 文件即可触发”,范围过宽,尤其“上传 PDF 文件即可触发”会让任意 PDF 上传场景都可能误调用该技能。对处理敏感合同内容的技能而言,误触发可能导致用户在未充分知情或未明确授权的情况下将文档内容送入分析流程和外部模型接口。

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill performs subscription/API-key verification against https://api.yk-global.com/v1/verify, which is unrelated to the stated contract-analysis functionality and creates an additional external data flow for user credentials. In a document-analysis skill, unexpected credential transmission to a separate service increases supply-chain and privacy risk, especially because users may not expect their provided key to be sent off-platform.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

The hardcoded verification endpoint represents external transmission of sensitive authentication material to a third-party domain. In the context of a contract-review skill, this is more suspicious because the network destination is not directly tied to the core document-analysis task, increasing the risk of unexpected credential disclosure or service impersonation if the endpoint is untrusted.

Content

Scanner excerpt · scripts/analyze_contract.py (reported line 18)May include surrounding context.

python
from pathlib import Path

# ── 91Skillhub Token Verification ─────────────────────────────────────────────
VERIFY_URL = "https://api.yk-global.com/v1/verify"


def _map_prefix_to_tier(api_key: str) -> str:

External Transmission

Medium
Category
Data Exfiltration
Confidence
99% confidence
Finding

The code is configured to send prompts containing contract text to https://api.minimax.chat/v1, which is an external service. Since the prompt includes substantial portions of the contract, this creates direct exposure of confidential legal information to a third party and can trigger privacy, confidentiality, and regulatory concerns.

Content

Scanner excerpt · scripts/analyze_contract.py (reported line 267)May include surrounding context.

python
import os

    api_key = os.environ.get("OPENAI_API_KEY", "")
    base_url = os.environ.get("OPENAI_API_BASE", "https://api.minimax.chat/v1")

    if not api_key:
        # Fallback: try direct OpenAI

External Transmission

Medium
Category
Data Exfiltration
Confidence
99% confidence
Finding

The fallback to https://api.openai.com/v1 introduces another external destination that may receive full contract content without any additional user approval. Multiple possible providers increase uncertainty about where sensitive documents are processed, retained, and governed, which is especially risky for legal documents.

Content

Scanner excerpt · scripts/analyze_contract.py (reported line 272)May include surrounding context.

python
if not api_key:
        # Fallback: try direct OpenAI
        api_key = os.environ.get("OPENAI_API_KEY_FALLBACK", "")
        base_url = os.environ.get("OPENAI_API_BASE_FALLBACK", "https://api.openai.com/v1")

    if not api_key:
        return {"error": "No API key configured. Set OPENAI_API_KEY or OPENAI_API_KEY_FALLBACK environment variable."}

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

Report rendering is hard-coded in Chinese, and the prompt also instructs risk titles to be in Chinese or English matching the contract language without giving the user a configurable locale choice. This can violate language/locale policy because the skill imposes a specific output language behavior rather than offering opt-in or selection.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill sends contract text to an external LLM API for analysis, and the code provides no user-facing warning, confirmation, or redaction step before transmitting potentially sensitive legal and commercial content. Because contracts commonly contain confidential terms, personal data, and trade secrets, silent exfiltration to third-party AI providers creates a meaningful confidentiality and compliance risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The instructions specify running OCR with 'chi_sim + eng' and falling back to Chinese + English bilingual OCR. This imposes a language/locale constraint in the skill's natural-language behavior without user opt-in or a clearly documented reason that the skill only supports those languages.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency is specified with a lower-bound version constraint instead of an exact pinned version, which makes builds non-reproducible and allows future package releases to be installed without review. This increases supply-chain risk because a later vulnerable or malicious release could be pulled into the environment unexpectedly.

Content

Scanner excerpt · scripts/requirements.txt (reported line 4)May include surrounding context.

text
# Contract Risk Reviewer - Python Dependencies
# Install with: pip install -r requirements.txt

PyMuPDF>=1.23.0
pdfplumber>=0.10.0
pytesseract>=0.3.10
pdf2image>=1.16.0

Unverifiable Dependency: PyMuPDF has 2 known advisory(ies) (CVE-2026-3029 (PyMuPDF has a path traversal in _main_.py); CVE-2026-3029 (PyMuPDF has a path traversal in _main_.py)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
88% confidence
Finding

PyMuPDF is referenced without a pinned version even though advisories exist for some releases, so it is impossible to determine from this manifest whether the installed version is affected. In a skill that processes PDFs, that uncertainty matters more because document-parsing libraries are exposed to attacker-controlled files and have a history of security issues.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

Using an unpinned minimum version for pdfplumber permits installation of newer unreviewed releases, reducing reproducibility and increasing exposure to supply-chain compromise or newly introduced defects. While not an immediate exploit by itself, it weakens dependency integrity controls.

Content

Scanner excerpt · scripts/requirements.txt (reported line 5)May include surrounding context.

text
# Install with: pip install -r requirements.txt

PyMuPDF>=1.23.0
pdfplumber>=0.10.0
pytesseract>=0.3.10
pdf2image>=1.16.0
openai>=1.0.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The pytesseract dependency is not pinned to a specific version, so environments may resolve to different releases over time. This creates a supply-chain and reproducibility risk because a bad upstream release could be consumed automatically.

Content

Scanner excerpt · scripts/requirements.txt (reported line 6)May include surrounding context.

text
PyMuPDF>=1.23.0
pdfplumber>=0.10.0
pytesseract>=0.3.10
pdf2image>=1.16.0
openai>=1.0.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

An unpinned pdf2image requirement allows package resolution to drift to newer versions that have not been vetted in this skill. This can introduce unexpected vulnerabilities, behavior changes, or malicious supply-chain content.

Content

Scanner excerpt · scripts/requirements.txt (reported line 7)May include surrounding context.

text
PyMuPDF>=1.23.0
pdfplumber>=0.10.0
pytesseract>=0.3.10
pdf2image>=1.16.0
openai>=1.0.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The openai package is declared with only a minimum version, allowing any later release to be installed. That broad range increases supply-chain exposure and may introduce breaking or insecure changes without deliberate approval.

Content

Scanner excerpt · scripts/requirements.txt (reported line 8)May include surrounding context.

text
pdfplumber>=0.10.0
pytesseract>=0.3.10
pdf2image>=1.16.0
openai>=1.0.0

Static analysis

No suspicious patterns detected.