diff --git a/infer/src/clang/cFrontend_errors.ml b/infer/src/clang/cFrontend_errors.ml
index 68959978f..9148bb266 100644
--- a/infer/src/clang/cFrontend_errors.ml
+++ b/infer/src/clang/cFrontend_errors.ml
@@ -18,7 +18,8 @@ type linter = {
   condition : CTL.t;
   issue_desc : CIssue.issue_desc;
   def_file : string option;
-  path : string option;
+  whitelist_paths : ALVar.t list;
+  blacklist_paths : ALVar.t list;
 }
 
 (* If in linter developer mode and if current linter was passed, filter it out *)
@@ -37,9 +38,16 @@ let filter_parsed_linters_developer parsed_linters =
 
 let filter_parsed_linters_by_path parsed_linters source_file =
   let filter_parsed_linter_by_path linter =
-    match linter.path with
-    | Some path -> ALVar.str_match_regex (SourceFile.to_rel_path source_file) path
-    | None -> true in
+    let should_lint paths =
+      List.exists
+        ~f:(fun path -> ALVar.compare_str_with_alexp (SourceFile.to_rel_path source_file) path)
+        paths in
+    let whitelist_ok =
+      List.is_empty linter.whitelist_paths || should_lint linter.whitelist_paths in
+    let blacklist_ok =
+      List.is_empty linter.blacklist_paths ||  not (should_lint linter.blacklist_paths) in
+    whitelist_ok && blacklist_ok
+  in
   List.filter ~f:filter_parsed_linter_by_path parsed_linters
 
 let filter_parsed_linters parsed_linters source_file =
@@ -162,30 +170,32 @@ let create_parsed_linters linters_def_file checkers : linter list =
       severity = Exceptions.Kwarning;
       mode = CIssue.On;
     } in
-    let issue_desc, condition, path =
-      let process_linter_definitions (issue, cond, path) description =
+    let issue_desc, condition, whitelist_paths, blacklist_paths =
+      let process_linter_definitions (issue, cond, wl_paths, bl_paths) description =
         match description with
         | CSet (av, phi) when ALVar.is_report_when_keyword av ->
-            issue, phi, path
+            issue, phi, wl_paths, bl_paths
         | CDesc (av, msg) when ALVar.is_message_keyword av ->
-            {issue with description = msg}, cond, path
+            {issue with description = msg}, cond, wl_paths, bl_paths
         | CDesc (av, sugg) when ALVar.is_suggestion_keyword av ->
-            {issue with suggestion = Some sugg}, cond, path
+            {issue with suggestion = Some sugg}, cond, wl_paths, bl_paths
         | CDesc (av, sev) when ALVar.is_severity_keyword  av ->
-            {issue with severity = string_to_err_kind sev}, cond, path
+            {issue with severity = string_to_err_kind sev}, cond, wl_paths, bl_paths
         | CDesc (av, m) when ALVar.is_mode_keyword  av ->
-            {issue with mode = string_to_issue_mode m }, cond, path
-        | CDesc (av, path') when ALVar.is_path_keyword av ->
-            issue, cond, string_to_path path'
-        | _ -> issue, cond, path in
+            {issue with mode = string_to_issue_mode m }, cond, wl_paths, bl_paths
+        | CPath (`WhitelistPath, paths) ->
+            issue, cond, paths, bl_paths
+        | CPath (`BlacklistPath, paths) ->
+            issue, cond, wl_paths, paths
+        | _ -> issue, cond, wl_paths, bl_paths in
       List.fold
         ~f:process_linter_definitions
-        ~init:(dummy_issue, CTL.False, None)
+        ~init:(dummy_issue, CTL.False, [], [])
         checker.definitions in
     L.(debug Linters Medium) "@\nMaking condition and issue desc for checker '%s'@\n" checker.name;
     L.(debug Linters Medium) "@\nCondition =@\n    %a@\n" CTL.Debug.pp_formula condition;
     L.(debug Linters Medium) "@\nIssue_desc = %a@\n" CIssue.pp_issue issue_desc;
-    {condition; issue_desc; def_file = Some linters_def_file; path;} in
+    {condition; issue_desc; def_file = Some linters_def_file; whitelist_paths; blacklist_paths;} in
   List.map ~f:do_one_checker checkers
 
 let rec apply_substitution f sub =
diff --git a/infer/src/clang/cFrontend_errors.mli b/infer/src/clang/cFrontend_errors.mli
index 18b213abf..63f7016c3 100644
--- a/infer/src/clang/cFrontend_errors.mli
+++ b/infer/src/clang/cFrontend_errors.mli
@@ -13,7 +13,8 @@ type linter = {
   condition : CTL.t;
   issue_desc : CIssue.issue_desc;
   def_file : string option;
-  path : string option;
+  whitelist_paths : ALVar.t list;
+  blacklist_paths : ALVar.t list;
 }
 
 val filter_parsed_linters : linter list -> SourceFile.t -> linter list
diff --git a/infer/src/clang/cTL.ml b/infer/src/clang/cTL.ml
index 49b0f52f5..dd32d6d50 100644
--- a/infer/src/clang/cTL.ml
+++ b/infer/src/clang/cTL.ml
@@ -77,10 +77,12 @@ let has_transition phi = match phi with
    set message = "bla"
 
 *)
+
 type clause =
   | CLet of ALVar.formula_id * ALVar.t list * t (* Let clause: let id = definifion;  *)
   | CSet of ALVar.keyword * t (* Set clause: set id = definition *)
   | CDesc of ALVar.keyword * string (* Description clause eg: set message = "..." *)
+  | CPath of [ `WhitelistPath | `BlacklistPath ] * ALVar.t list
 
 type ctl_checker = {
   name : string; (* Checker's name *)
@@ -441,7 +443,14 @@ let print_checker c =
             cn_str Debug.pp_formula phi
       | CDesc (keyword, s) ->
           let cn_str = ALVar.keyword_to_string keyword in
-          L.(debug Linters Medium) "    %s=  @\n    %s@\n@\n" cn_str s)
+          L.(debug Linters Medium) "    %s=  @\n    %s@\n@\n" cn_str s
+      | CPath (paths_keyword, paths) ->
+          let keyword =
+            (match paths_keyword with
+             | `WhitelistPath -> "whitelist_path"
+             | _ -> "blacklist_path") in
+          let paths_str = String.concat ~sep:"," (List.map ~f:ALVar.alexp_to_string paths) in
+          L.(debug Linters Medium) "    %s=  @\n    %s@\n@\n" keyword paths_str)
     ) c.definitions;
   L.(debug Linters Medium) "@\n-------------------- @\n"
 
diff --git a/infer/src/clang/cTL.mli b/infer/src/clang/cTL.mli
index b3dbc3ba5..c5c550f69 100644
--- a/infer/src/clang/cTL.mli
+++ b/infer/src/clang/cTL.mli
@@ -80,6 +80,7 @@ type clause =
   | CLet  of ALVar.formula_id * ALVar.t list * t (* Let clause: let id = definifion;  *)
   | CSet of ALVar.keyword * t (* Set clause: set id = definition *)
   | CDesc of ALVar.keyword * string (* Description clause eg: set message = "..." *)
+  | CPath of [ `WhitelistPath | `BlacklistPath ] * ALVar.t list
 
 type ctl_checker = {
   name : string; (* Checker's name *)
diff --git a/infer/src/clang/ctl_lexer.mll b/infer/src/clang/ctl_lexer.mll
index 5584d1275..306b1f473 100644
--- a/infer/src/clang/ctl_lexer.mll
+++ b/infer/src/clang/ctl_lexer.mll
@@ -54,6 +54,8 @@ rule token = parse
   | "LET" { LET }
   | "TRUE" { TRUE }
   | "FALSE" { FALSE }
+  | "whitelist_path" { WHITELIST_PATH }
+  | "blacklist_path" { BLACKLIST_PATH }
   | "{" { LEFT_BRACE }
   | "}" { RIGHT_BRACE }
   | "(" { LEFT_PAREN }
diff --git a/infer/src/clang/ctl_parser.mly b/infer/src/clang/ctl_parser.mly
index fab84e211..a27dbc380 100644
--- a/infer/src/clang/ctl_parser.mly
+++ b/infer/src/clang/ctl_parser.mly
@@ -67,6 +67,8 @@
 %token <string> IDENTIFIER
 %token <string> FILE_IDENTIFIER
 %token <string> STRING
+%token WHITELIST_PATH
+%token BLACKLIST_PATH
 %token EOF
 
 /* associativity and priority (lower to higher) of operators */
@@ -125,6 +127,11 @@ checker:
   }
 ;
 
+path_list:
+ | alexp { [$1] }
+ | alexp COMMA path_list { $1 :: $3 }
+;
+
 clause_list:
  | clause SEMICOLON { [$1] }
  | clause SEMICOLON clause_list { $1 :: $3 }
@@ -143,6 +150,10 @@ clause:
       | _ -> failwith "string '%s' cannot be set to a variable. \
                        Use the reserverd variable 'report_when'" in
       CTL.CSet (alvar, $4) }
+  | SET WHITELIST_PATH ASSIGNMENT LEFT_BRACE path_list RIGHT_BRACE
+    { CTL.CPath (`WhitelistPath, $5) }
+  | SET BLACKLIST_PATH ASSIGNMENT LEFT_BRACE path_list RIGHT_BRACE
+    { CTL.CPath (`BlacklistPath, $5) }
   | SET identifier ASSIGNMENT STRING
     { L.(debug Linters Verbose) "\tParsed SET clause@\n";
       let alvar = match $2 with
@@ -150,10 +161,9 @@ clause:
       | "suggestion" -> ALVar.Suggestion
       | "severity" -> ALVar.Severity
       | "mode" -> ALVar.Mode
-      | "path" -> ALVar.Path
       | _ -> failwithf "string '%s' cannot be set in a SET clause. \
                         Use either of: \
-                        'message', 'mode', 'severity', 'suggestion' or 'path'" $2 in
+                        'message', 'mode', 'severity' or 'suggestion'" $2 in
       CTL.CDesc (alvar, $4) }
     | let_clause { $1 }
     ;
diff --git a/infer/tests/codetoanalyze/objc/linters-for-test-only/issues.exp b/infer/tests/codetoanalyze/objc/linters-for-test-only/issues.exp
index a43281812..e79b27af1 100644
--- a/infer/tests/codetoanalyze/objc/linters-for-test-only/issues.exp
+++ b/infer/tests/codetoanalyze/objc/linters-for-test-only/issues.exp
@@ -2,7 +2,9 @@ codetoanalyze/objc/linters-for-test-only/filter_by_path/include_file.m, main, 9,
 codetoanalyze/objc/linters-for-test-only/filter_by_path/include_file.m, main, 9, FILTER_BY_ALL_PATH_EXAMPLE, []
 codetoanalyze/objc/linters-for-test-only/filter_by_path/include_file.m, main, 9, FILTER_BY_PATH_EXAMPLE, []
 codetoanalyze/objc/linters-for-test-only/implicit_cast.c, main, 9, ALL_PATH_NO_FILTER_EXAMPLE, []
+codetoanalyze/objc/linters-for-test-only/implicit_cast.c, main, 9, BLACKLIST_PATH_EXAMPLE, []
 codetoanalyze/objc/linters-for-test-only/implicit_cast.c, main, 9, FILTER_BY_ALL_PATH_EXAMPLE, []
+codetoanalyze/objc/linters-for-test-only/implicit_cast.c, main, 9, WHITE_BLACKLIST_PATH_EXAMPLE, []
 codetoanalyze/objc/linters-for-test-only/implicit_cast.c, main, 10, TEST_VAR_TYPE_CHECK, []
 codetoanalyze/objc/linters-for-test-only/implicit_cast.c, main, 11, TEST_IMPLICIT_CAST_CHECK, []
 codetoanalyze/objc/linters-for-test-only/implicit_cast.c, main, 11, TEST_VAR_TYPE_CHECK, []
diff --git a/infer/tests/codetoanalyze/objc/linters-for-test-only/linters_example.al b/infer/tests/codetoanalyze/objc/linters-for-test-only/linters_example.al
index 20cfe0fc4..2f99ba059 100644
--- a/infer/tests/codetoanalyze/objc/linters-for-test-only/linters_example.al
+++ b/infer/tests/codetoanalyze/objc/linters-for-test-only/linters_example.al
@@ -242,7 +242,7 @@ DEFINE-CHECKER FILTER_BY_PATH_EXAMPLE = {
      WHEN declaration_has_name("main")
      HOLDS-IN-NODE FunctionDecl;
   SET message = "Found main method";
-  SET path = "codetoanalyze/objc/linters-for-test-only/filter_by_path/.*";
+  SET whitelist_path = { REGEXP("codetoanalyze/objc/linters-for-test-only/filter_by_path/.*"), "A.m" };
 };
 
 DEFINE-CHECKER ALL_PATH_NO_FILTER_EXAMPLE = {
@@ -257,5 +257,22 @@ DEFINE-CHECKER FILTER_BY_ALL_PATH_EXAMPLE = {
      WHEN declaration_has_name("main")
      HOLDS-IN-NODE FunctionDecl;
   SET message = "Found main method";
-  SET path = ".*";
+  SET whitelist_path = { REGEXP(".*") };
+};
+
+DEFINE-CHECKER BLACKLIST_PATH_EXAMPLE = {
+  SET report_when =
+     WHEN declaration_has_name("main")
+     HOLDS-IN-NODE FunctionDecl;
+  SET message = "Found main method";
+  SET blacklist_path = { REGEXP("codetoanalyze/objc/linters-for-test-only/filter_by_path/.*") };
+};
+
+DEFINE-CHECKER WHITE_BLACKLIST_PATH_EXAMPLE = {
+  SET report_when =
+     WHEN declaration_has_name("main")
+     HOLDS-IN-NODE FunctionDecl;
+  SET message = "Found main method";
+  SET whitelist_path = { REGEXP(".*") };
+  SET blacklist_path = { REGEXP("codetoanalyze/objc/linters-for-test-only/filter_by_path/.*") };
 };