Skip to content
cccskills
FreePublished on GitHub

appfolio-security-basics

Review an AppFolio integration’s credential handling, access scope, webhook signatures, and tenant-data protection. Get a security checklist and go/no-go findings, including logging and audit controls for sensitive records.

OriginalShow the original description

Secure AppFolio API credentials and tenant data. Trigger: "appfolio security".

Run score Not tested

See how to install

Good for

  • Preparing an AppFolio API integration for production
  • Checking webhook signature handling
  • Reviewing tenant data logging and storage
  • Planning credential rotation and access scope

Files included (1)

  • SKILL.md6.0 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

AppFolio Security Basics

Overview

AppFolio manages property portfolios containing tenant PII (SSNs, bank accounts, lease terms), owner financial data, and maintenance vendor records. A breach exposes rent rolls, payment histories, and personally identifiable tenant information across every managed property. Secure every integration point: API credentials, webhook endpoints, and any pipeline that touches tenant or owner financial records.

Prerequisites

  • A verified AppFolio contract stating the permitted endpoint, authentication, webhook, data-retention, and portfolio-scoping requirements for the target environment.
  • A secret manager, separate sandbox credentials, and a named security owner for rotations, access review, and incident response.
  • A raw-body route configuration for any signed webhook: signature verification must run before JSON parsing, mutation, or logging of the request payload.

Instructions

  1. Load credentials from the approved secret boundary, validate the HTTPS base URL, and give each worker only the scope it requires.
  2. Receive webhook requests as bounded raw bytes, validate the signature shape and HMAC in constant time, then parse and schema-validate the payload.
  3. Encrypt or minimize sensitive stored fields, redact nested PII before logs, and record access through a durable audit trail.
  4. Run a rotation and webhook-negative-path rehearsal in sandbox; a failed signature, missing secret, or unverifiable endpoint is a no-go condition.

API Key Management

import https from "https";
import axios, { AxiosInstance } from "axios";

function createAppFolioClient(): AxiosInstance {
  const clientId = process.env.APPFOLIO_CLIENT_ID;
  const clientSecret = process.env.APPFOLIO_CLIENT_SECRET;
  const baseUrl = process.env.APPFOLIO_BASE_URL;
  if (!clientId || !clientSecret || !baseUrl) {
    throw new Error("Missing APPFOLIO_CLIENT_ID, APPFOLIO_CLIENT_SECRET, or APPFOLIO_BASE_URL");
  }
  return axios.create({
    baseURL: baseUrl,
    auth: { username: clientId, password: clientSecret },
    httpsAgent: new https.Agent({ minVersion: "TLSv1.2", rejectUnauthorized: true }),
  });
}

Webhook Signature Verification

import crypto from "crypto";

function verifyAppFolioWebhook(req: Request, res: Response, next: NextFunction): void {
  const signature = req.headers["x-appfolio-signature"] as string;
  const secret = process.env.APPFOLIO_WEBHOOK_SECRET!;
  // req.body must be a bounded raw Buffer from the route's raw-body middleware.
  const expected = Buffer.from(crypto.createHmac("sha256", secret).update(req.body).digest("hex"));
  const received = signature ? Buffer.from(signature) : Buffer.alloc(0);
  if (received.length !== expected.length || !crypto.timingSafeEqual(received, expected)) {
    res.status(401).send("Invalid signature");
    return;
  }
  next();
}

Input Validation

import { z } from "zod";
const TenantSchema = z.object({
  tenant_id: z.string().uuid(),
  first_name: z.string().min(1).max(100),
  last_name: z.string().min(1).max(100),
  email: z.string().email(),
  unit_id: z.string().uuid(),
  lease_start: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
  rent_amount: z.number().positive().max(100000),
});

function validateTenantPayload(data: unknown) {
  return TenantSchema.parse(data);
}

Data Protection

const APPFOLIO_PII_FIELDS = ["ssn", "bank_account", "routing_number", "date_of_birth", "drivers_license"];

function redactAppFolioLog(record: Record<string, unknown>): Record<string, unknown> {
  const redacted = { ...record };
  for (const field of APPFOLIO_PII_FIELDS) {
    if (field in redacted) redacted[field] = "[REDACTED]";
  }
  return redacted;
}

Security Checklist

  • API credentials stored in secrets manager, not .env in production
  • HTTPS enforced with TLS 1.2+ for all API calls
  • Tenant SSN and bank account numbers never logged
  • Webhook signatures verified on every inbound request
  • API credentials rotated quarterly
  • Access scoped to minimum required property endpoints
  • Rent payment data encrypted at rest
  • Audit trail enabled for tenant record access

Output

  • A least-privilege, TLS-validated client configuration with no credential material written to logs or source
  • A fail-closed webhook decision before payload parsing or downstream mutation
  • A redacted audit record and a security go/no-go result for each integration change or credential rotation

Examples

For a webhook onboarding rehearsal, use a synthetic sandbox payload and test the valid signature, a missing signature, a malformed-length signature, and a replayed event. Confirm that only the valid raw-body request reaches the schema parser, while rejected attempts create a redacted security event and no tenant record change. If raw-body handling, secret access, signature validation, or audit persistence is unavailable, disable the endpoint and remediate before accepting production events.

Error Handling

VulnerabilityRiskMitigation
Leaked API credentialsFull property portfolio exposureSecrets manager + rotation
Unvalidated webhook payloadsSpoofed tenant updatesHMAC signature verification
Tenant PII in logsCompliance violation (state privacy laws)Field-level redaction
Overly broad API scopeLateral access to unrelated propertiesPer-property credential scoping
Unencrypted payment dataFinancial data breachTLS 1.2+ in transit, AES at rest

Resources

Next Steps

See appfolio-prod-checklist.

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Add a synthetic-data CI gate for customer-owned Abridge integration code. Test consent handling, note-review handoffs, redaction, and rollback behavior with mocked vendor boundaries, without connecting CI to a live Abridge or EHR tenant.

  • Adding regression checks to an Abridge integration repository
  • Testing consent and note-release handling
  • Checking logs for sensitive data exposure
jeremylongshore/tons-of-skills-marketplace2.9KUpdated Oct 23, 2026

Triage Abridge recording, note review, Epic handoff, and access problems using observed symptoms and approved guidance. Identify the affected workflow stage, organize a minimal timeline, and prepare a redacted escalation record for the responsible team.

  • Separate recording problems from upload failures
  • Investigate note creation delays and editor issues
  • Identify the responsible team for Epic handoff failures
jeremylongshore/tons-of-skills-marketplace2.9KUpdated Oct 23, 2026

Map and review an Abridge clinical documentation workflow from consent and recording through draft review, evidence checks, edits, and final disposition. Keep clinician approval explicit, identify failure exits, and separate verified facts from tenant-specific details and pending approvals.

  • Map a clinical note workflow for a care setting
  • Check where consent and patient identity are verified
  • Review draft notes against linked evidence before sign-off
jeremylongshore/tons-of-skills-marketplace2.9KUpdated Oct 23, 2026

Audit how clinician-reviewed Abridge note sections map into Epic templates and downstream workflows. Use approved test records to document destinations, exceptions, evidence, rollback steps, and a go or no-go decision for a specific environment.

  • Checking Abridge note section mappings to Epic templates
  • Auditing a department’s approved documentation handoff
  • Preparing test evidence and a go or no-go decision
jeremylongshore/tons-of-skills-marketplace2.9KUpdated Oct 23, 2026

Review Abridge adoption and workflow value using local usage records, clinician feedback, and verified contract costs. Build an evidence based decision table covering adoption, quality, support burden, and options to expand, hold, or improve the rollout.

  • Reviewing adoption after an Abridge rollout
  • Preparing evidence for a renewal decision
  • Comparing workflow outcomes across care settings
jeremylongshore/tons-of-skills-marketplace2.9KUpdated Oct 23, 2026

Prepare a bounded support bundle for an Abridge issue using allowlisted operational details such as versions, coarse timestamps, and correlation references. Exclude recordings, transcripts, patient identifiers, credentials, and unrestricted logs, then document redactions and review details.

  • Preparing reviewed evidence for an Abridge support case
  • Documenting redactions and excluded data
  • Collecting approved operational details for an incident
jeremylongshore/tons-of-skills-marketplace2.9KUpdated Oct 23, 2026

See all skills by jeremylongshore

Report a problem with this skill