Why Managed Packages Fail Security Review: CRUD/FLS Mistakes That Cost You 8 Weeks

Salesforce

5 MIN READ

October 23, 2026

Loading

salesforce developer reviewing apex code on a computer screen to fix crud and fls security review mistakes

Did you know that a few lines of Apex code that bypass CRUD or Field-Level Security (FLS) can delay an otherwise launch-ready Salesforce product by weeks? For a CTO, that means a delayed AppExchange launch, additional engineering costs, missed revenue opportunities, and a sales team waiting for a product they cannot yet take to market. 

Salesforce keeps on updating its AppExchange partner security standards, raising the bar even higher for automated source code checks and third-party API validations.

For many independent software vendors (ISVs) leveraging specialized Salesforce AppExchange App Development Services, the reality hits hard: industry data across the ecosystem shows nearly 80% of first-time managed package submissions fail the AppExchange security review. 

What is the single biggest culprit behind these rejections? Improper CRUD permissions and FLS enforcement.

When your submission fails, you don’t just lose time fixing code. You enter a re-review queue that can easily add 6 to 8 weeks of delay, wasting developer hours, burning through launch budgets, and stalling sales cycles.

So, what exactly is Salesforce looking for when it reviews your Apex code, which CRUD/FLS mistakes trigger rejection, and how can you catch these issues before they cost your team another 6 to 8 weeks? 

The True Cost of Security Review Failure for a Salesforce ISV

For a decision-maker, an AppExchange rejection isn’t just a developer issue; it’s a business crisis. If you want to understand how launching smoothly impacts your business ROI, read our guide on how to Boost Your Business Growth with Salesforce AppExchange. 

When your managed package gets flagged, the domino effect impacts every department: 

  • Stalled Revenue: Enterprise buyers will not install unapproved applications. Every week in review limbo means delayed contract signatures.
  • Burned Developer Hours: Instead of building new roadmap features, your engineering team must drop everything to perform manual code audits across thousands of lines of Apex.
  • Resubmission Fees and Delays: Beyond the monetary costs, waiting for a re-review slot severely disrupts product launch timelines and marketing campaigns.

Most partners assume that if their code runs smoothly and passes unit tests, it’s secure. However, Salesforce operates on a shared responsibility model. By default, Apex runs in System mode, meaning it bypasses the target user’s object-level (CRUD) and field-level (FLS) security settings.

If your app displays or modifies data that a user shouldn’t see or touch in their Salesforce org, the Checkmarx scanner and Salesforce’s security team will reject your app immediately.

Understanding the Essentials: CRUD vs. FLS vs. Sharing Rules

Before diving into specific code fixes, let’s clear up the terminology that frequently confuses development teams preparing for an Meta Description (155 chars):Explore how unifying quote-to-cash using Revenue Cloud drives enterprise growth, streamlines key billing steps, and accelerates overall revenue realization.

Security Layer

Enforcement Level Core Security Question
CRUD Permissions Object Level

Can the user Create, Read, Update, or Delete this Object?

FLS Enforcement

Field Level Can the user Read or Edit a specific Field?
Sharing Rules Record Level

Which specific records can the user see? (with sharing)

 

  1. CRUD (Create, Read, Update, Delete): Controls permissions at the Object level. (Example: Can this user edit Account records?)
  2. FLS (Field-Level Security): Controls access at the Field level within an object. (Example: Can this user see the SSN__c or Salary__c field on a Contact record?)
  3. Sharing Rules: Controls access at the Record level. (Example: Can User A see User B’s specific Opportunity record?)

If your Apex code updates a custom record without verifying that the current user has Update permissions on both the object AND the specific fields being written, you have created a security vulnerability.

3 Fatal CRUD/FLS Mistakes That Trigger Security Review Rejections

Let’s review the three most common technical missteps that cause packages to fail the AppExchange security review.

Mistake 1: Relying Solely on with sharing

Many developers believe adding with sharing to an Apex class header completely secures their code. This is a critical misconception.

with sharing only enforces Record-Level Sharing Rules. It determines which records a user can see, but it does not prevent a user from reading or writing to fields they don’t have permission to access via FLS.

Bad Example:

// WRONG: ‘with sharing’ does NOT enforce CRUD or FLS!

public with sharing class InvoiceController {

    public static void updateDiscount(Id invoiceId, Decimal newDiscount) {

        // System mode executes DML without checking FLS on Discount_Rate__c

        Invoice__c inv = [SELECT Id, Discount_Rate__c FROM Invoice__c WHERE Id = :invoiceId];

        inv.Discount_Rate__c = newDiscount;

        update inv; 

    }

}

Why it fails security review: If a standard user calls this method, they can update Discount_Rate__c even if their Salesforce Profile explicitly hides or locks that field.

Mistake 2: Missing Checks Before DML Operations (Insert/Update)

Another common error occurs when developers read data safely but forget to validate permissions before performing Data Manipulation Language (DML) operations like INSERT, UPDATE, or DELETE.

Use Case: Customer Portal Case Creation

Imagine an app that allows portal users to submit feedback cases. If the Apex controller inserts incoming fields into custom fields without checking field-level write permissions, a malicious user could tamper with hidden system fields.

Bad Example:

// WRONG: Direct DML without Schema checks

public class CaseService {

    public static void createFeedbackCase(String subject, String priority) {

        Case c = new Case(

            Subject = subject,

            Priority = priority,

            Internal_Notes__c = ‘Created via Portal App’

        );

        insert c; // Fails review: No check for Create access on Case or fields

    }

}

Mistake 3: Bypassing Security for “System Tasks” Without Documentation

There are legitimate scenarios where a managed package must run in system mode—such as logging error messages to a custom object (App_Log__c) where end-users don’t have direct read/write access.

However, if you execute DML in system mode without documenting the business justification, the Checkmarx scanner flags it automatically. Refer to the official Salesforce Secure Coding Guidelines for CRUD/FLS for security compliance standards. Additionally, explore our best practices for secure connectivity in our guide on Salesforce Integration Best Practices.

How to Fix CRUD/FLS Violations in Salesforce Apex

Salesforce has introduced modern, developer-friendly features that make enforcing CRUD permissions and FLS enforcement much easier than in the past.

Here is how to fix violations using modern Apex security tools.

Solution 1: Use WITH USER_MODE in SOQL Queries

Historically, developers used WITH SECURITY_ENFORCED in SOQL queries. While effective for SELECT queries, WITH USER_MODE is now the recommended modern standard because it applies uniformly across SOQL queries, Database methods, and DML operations.

Comparing SOQL Options:

Feature

WITH SECURITY_ENFORCED WITH USER_MODE
Supported Operations SOQL SELECT only

SOQL queries AND DML statements

Polymorphic Lookup Support

Limited Comprehensive
Exception Handling Throws System.QueryException

Throws standard, catchable exceptions

Salesforce Recommendation

Legacy Standard

Current Best Practice

Good Example (WITH USER_MODE in SOQL):

// CORRECT: Enforces object and field read access natively

public with sharing class AccountSelector {

    public static List getActiveAccounts() {

        return [

            SELECT Id, Name, AnnualRevenue, Industry 

            FROM Account 

            WHERE Active__c = ‘Yes’ 

            WITH USER_MODE // Rejects query if user lacks read access to any requested field

        ];

    }

}

Good Example (USER_MODE in DML):

// CORRECT: Native DML enforcement in User Mode

public with sharing class AccountService {

    public static void updateAccountRevenue(Account accToUpdate) {

        // Automatically checks if user has UPDATE permissions on object and fields

        Database.update(accToUpdate, AccessLevel.USER_MODE);

    }

}

Solution 2: Use Security.stripInaccessible() for Flexible Data Handling

Sometimes you want to process incoming data or queries gracefully without throwing fatal exceptions if a user lacks access to a few fields. This is where Apex Security.stripInaccessible best practices come into play.

Security.stripInaccessible() strips out fields that the current user is not allowed to see or modify, while leaving accessible data intact. This is especially critical when handling raw payload data using Salesforce Connector Development Services.  

Real-World Example: Updating Contact Details

Suppose your app provides a multi-field form for updating contact information. If a user lacks permission to update Title, stripInaccessible() simply drops Title from the update request, while still updating Phone and Email.

// CORRECT: Gracefully handling inaccessible fields during updates

public with sharing class ContactManager {

    public static void updateContactInfo(Contact inputContact) {

        List contactsToUpdate = new List{ inputContact };

 

        // Strip fields that the user does not have permission to UPDATE

        SObjectAccessDecision decision = Security.stripInaccessible(

            AccessType.UPDATABLE, 

            contactsToUpdate

        );

 

        // Update the sanitized records safely

        update decision.getRecords();

    }

}

Solution 3: Manual Schema Permission Checks (When Fine Control is Needed)

For custom business logic or complex conditional user interfaces, you can explicitly check permissions using Schema.DescribeSObjectResult and Schema.DescribeFieldResult. If your org requires customized architectural controls, learn more about our tailored Salesforce Customization Services.

// CORRECT: Manual check before executing custom logic

public with sharing class CustomBillingService {

    public static void applyDiscount(Opportunity opp) {

        // Verify Object-Level Update Permission

        if (!Schema.sObjectType.Opportunity.isUpdateable()) {

            throw new AuraHandledException(‘Insufficient permissions to update Opportunities.’);

        }

        // Verify Field-Level Update Permission

        if (!Schema.sObjectType.Opportunity.fields.Amount.isUpdateable()) {

            throw new AuraHandledException(‘You do not have permission to edit Opportunity Amount.’);

        }

        opp.Amount = opp.Amount * 0.90;

        update opp;

    }

}

How to Pass Salesforce Security Review on the First Attempt

Executing a structured quality assurance process before submitting your package protects your product roadmap from unexpected review rejections. Follow this step-by-step pre-submission checklist to safeguard your launch timeline and ensure immediate compliance with platform standards.

Step 1: Run Automated Scans

Scan your entire codebase using Salesforce Code Analyzer and Checkmarx static security testing tools to discover potential vulnerabilities early. Review the output thoroughly and address every high and medium-severity finding before proceeding to human evaluation.

Step 2: Modernize Apex Security Syntax

Replace all legacy DML operations with AccessLevel.USER_MODE to natively enforce field and object permissions during database writes. Append WITH USER_MODE to all user-facing SOQL queries to guarantee uniform security enforcement across your application.

Step 3: Implement Graceful Security Handling

Apply Security.stripInaccessible() across multi-field form inputs and external system integrations to strip restricted fields automatically. This prevents unhandled security exceptions while keeping data operations completely compliant with end-user permissions.

Step 4: Audit System Mode Usage

Verify that every class defined with without sharing has an explicit, documented business requirement for escalating system privileges. Prepare clear false-positive documentation detailing why intentional system-mode execution is required for those specific use cases.

Step 5: Conduct End-to-End Persona Testing

Test your package functionality across restricted user profiles, such as the Minimum Access Profile, to validate access controls in real-time. Ensure that features function without throwing unexpected security errors or permitting unauthorized data modifications.

To see how end-to-end security and quality standards are applied in complex enterprise projects, read our Salesforce Maintenance & Security Integration Case Study.

Final Thoughts

Failing the AppExchange security review is rarely caused by a lack of developer talent. Most often, it happens because teams focus entirely on product features and treat security validation as an afterthought right before launch.

By adopting WITH USER_MODE, mastering Security.stripInaccessible(), and enforcing strict CRUD/FLS checks throughout your development cycle, your team can eliminate security roadblocks, safeguard customer data, and launch your managed package on schedule.

Navigating AppExchange compliance doesn’t have to stall your growth. As a trusted Salesforce Summit Consulting Partner, Ksolves specializes in end-to-end AppExchange app development, security review remediation, and code audits. 

Our certified Salesforce experts ensure your managed package meets every security standard, helping you pass the review on your first attempt and launch without costly delays. 

Frequently Asked Questions 

What is the difference between CRUD and FLS in Salesforce?

CRUD (Create, Read, Update, Delete) controls whether a user profile can perform actions on an entire object type. FLS (Field-Level Security) determines whether a user can read or edit specific fields within that object.

Why does Checkmarx flag my SOQL queries even when I use with sharing?

with sharing only enforces record-level access rules, not field or object permissions. Checkmarx flags SOQL queries lacking WITH USER_MODE or explicit schema checks because missing FLS/CRUD protection allows users to access restricted fields.

Should I use WITH USER_MODE or Security.stripInaccessible()?

Use WITH USER_MODE when you want queries or DML operations to throw an exception if the user lacks permissions. Use Security.stripInaccessible() when you want to silently remove inaccessible fields and proceed with the remaining data gracefully.

How do I handle System Mode execution for background processes?

If your app must execute in System Mode (e.g., writing error logs), document the business justification in a dedicated false-positive document for the AppExchange review team and ensure input parameters are strictly validated to prevent exploit vectors.

What happens if my AppExchange package fails the security review?

You will receive a detailed report outlining security violations (such as CRUD/FLS failures). You must remediate all issues in your codebase, re-test, and resubmit, which typically delays your market launch by 6 to 8 weeks.

loading

AUTHOR

Rakesh Kumar
Rakesh Kumar

Salesforce

Rakesh Kumar is a Salesforce Practice Lead and Application Architect at Ksolves India Limited, with over 11 years of experience in Salesforce development and enterprise solution architecture. He specializes in Salesforce Financial Services Cloud, Consumer Goods Cloud, Sales Cloud, Service Cloud, Commerce Cloud, Revenue Cloud, Data Cloud, and Agentforce. His expertise includes designing multi-cloud CRM solutions, integrating enterprise systems, developing reusable Salesforce accelerators, and implementing AI-driven workflows. A 12-time Salesforce-certified professional, Rakesh focuses on enterprise architecture, secure AI agent deployment, and transforming complex business processes into scalable, production-ready Salesforce solutions.

Leave a Comment

Your email address will not be published. Required fields are marked *

(Text Character Limit 350)

Global Presence
Follow Us
Copyright 2026© Ksolves.com | All Rights Reserved
Ksolves USP